blob: 747aaff7d99a120100631322a5bfc308371274f1 [file] [log] [blame]
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2013-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 unit tests for the CHIP TLV implementation.
*
*/
#include <nlbyteorder.h>
#include <nlunit-test.h>
#include <lib/core/CHIPCircularTLVBuffer.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/CHIPTLVData.hpp>
#include <lib/core/CHIPTLVDebug.hpp>
#include <lib/core/CHIPTLVUtilities.hpp>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ScopedBuffer.h>
#include <lib/support/UnitTestContext.h>
#include <lib/support/UnitTestExtendedAssertions.h>
#include <lib/support/UnitTestRegistration.h>
#include <lib/support/UnitTestUtils.h>
#include <lib/support/logging/Constants.h>
#include <system/TLVPacketBufferBackingStore.h>
#include <stdlib.h>
#include <string.h>
using namespace chip;
using namespace chip::TLV;
enum
{
TestProfile_1 = 0xAABBCCDD,
TestProfile_2 = 0x11223344,
TestProfile_3 = 0x11223355
};
// clang-format off
static const char sLargeString [] =
"START..."
"!123456789ABCDEF@123456789ABCDEF#123456789ABCDEF$123456789ABCDEF%123456789ABCDEF^123456789ABCDEF&123456789ABCDEF*123456789ABCDEF"
"01234567(9ABCDEF01234567)9ABCDEF01234567-9ABCDEF01234567=9ABCDEF01234567[9ABCDEF01234567]9ABCDEF01234567;9ABCDEF01234567'9ABCDEF"
"...END";
// clang-format on
void TestAndOpenContainer(nlTestSuite * inSuite, TLVReader & reader, TLVType type, Tag tag, TLVReader & containerReader)
{
NL_TEST_ASSERT(inSuite, reader.GetType() == type);
NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
NL_TEST_ASSERT(inSuite, reader.GetLength() == 0);
CHIP_ERROR err = reader.OpenContainer(containerReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, containerReader.GetContainerType() == type);
}
template <class T>
void TestAndEnterContainer(nlTestSuite * inSuite, T & t, TLVType type, Tag tag, TLVType & outerContainerType)
{
NL_TEST_ASSERT(inSuite, t.GetType() == type);
NL_TEST_ASSERT(inSuite, t.GetTag() == tag);
NL_TEST_ASSERT(inSuite, t.GetLength() == 0);
TLVType expectedContainerType = t.GetContainerType();
CHIP_ERROR err = t.EnterContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, outerContainerType == expectedContainerType);
NL_TEST_ASSERT(inSuite, t.GetContainerType() == type);
}
template <class T>
void TestNext(nlTestSuite * inSuite, T & t)
{
CHIP_ERROR err = t.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
void TestSkip(nlTestSuite * inSuite, TLVReader & reader)
{
CHIP_ERROR err = reader.Skip();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
void TestMove(nlTestSuite * inSuite, TLVUpdater & updater)
{
CHIP_ERROR err = updater.Move();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
template <class T>
void TestEnd(nlTestSuite * inSuite, T & t)
{
CHIP_ERROR err;
err = t.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
}
void TestEndAndCloseContainer(nlTestSuite * inSuite, TLVReader & reader, TLVReader & containerReader)
{
CHIP_ERROR err;
TestEnd<TLVReader>(inSuite, containerReader);
err = reader.CloseContainer(containerReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
template <class T>
void TestEndAndExitContainer(nlTestSuite * inSuite, T & t, TLVType outerContainerType)
{
CHIP_ERROR err;
TestEnd<T>(inSuite, t);
err = t.ExitContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, t.GetContainerType() == outerContainerType);
}
#define TEST_GET(inSuite, s, type, tag, expectedVal, expectedErr) \
do \
{ \
NL_TEST_ASSERT(inSuite, s.GetType() == type); \
NL_TEST_ASSERT(inSuite, s.GetTag() == tag); \
NL_TEST_ASSERT(inSuite, s.GetLength() == 0); \
\
decltype(expectedVal) __val; \
CHIP_ERROR __err = s.Get(__val); \
NL_TEST_ASSERT(inSuite, __err == expectedErr); \
if (__err == CHIP_NO_ERROR) \
{ \
NL_TEST_ASSERT(inSuite, __val == expectedVal); \
} \
} while (false)
#define TEST_GET_NOERROR(inSuite, s, type, tag, expectedVal) TEST_GET(inSuite, s, type, tag, expectedVal, CHIP_NO_ERROR)
void ForEachElement(nlTestSuite * inSuite, TLVReader & reader, void * context,
void (*cb)(nlTestSuite * inSuite, TLVReader & reader, void * context))
{
CHIP_ERROR err;
while (true)
{
err = reader.Next();
if (err == CHIP_END_OF_TLV)
{
return;
}
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
if (cb != nullptr)
{
cb(inSuite, reader, context);
}
if (TLVTypeIsContainer(reader.GetType()))
{
TLVType outerContainerType;
err = reader.EnterContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ForEachElement(inSuite, reader, context, cb);
err = reader.ExitContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
}
}
/**
* context
*/
struct TestTLVContext
{
nlTestSuite * mSuite = nullptr;
int mEvictionCount = 0;
uint32_t mEvictedBytes = 0;
TestTLVContext(nlTestSuite * suite) : mSuite(suite) {}
};
void TestNull(nlTestSuite * inSuite, TLVReader & reader, Tag tag)
{
NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_Null);
NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
NL_TEST_ASSERT(inSuite, reader.GetLength() == 0);
}
void TestString(nlTestSuite * inSuite, TLVReader & reader, Tag tag, const char * expectedVal)
{
NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_UTF8String);
NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
size_t expectedLen = strlen(expectedVal);
NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);
chip::Platform::ScopedMemoryBuffer<char> valBuffer;
char * val = static_cast<char *>(valBuffer.Alloc(expectedLen + 1).Get());
CHIP_ERROR err = reader.GetString(val, static_cast<uint32_t>(expectedLen) + 1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen + 1) == 0);
}
void TestDupString(nlTestSuite * inSuite, TLVReader & reader, Tag tag, const char * expectedVal)
{
NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_UTF8String);
NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
size_t expectedLen = strlen(expectedVal);
NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);
char * val = nullptr;
CHIP_ERROR err = reader.DupString(val);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, val != nullptr);
if (val != nullptr)
{
NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen + 1) == 0);
}
chip::Platform::MemoryFree(val);
}
void TestDupBytes(nlTestSuite * inSuite, TLVReader & reader, Tag tag, const uint8_t * expectedVal, uint32_t expectedLen)
{
NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_UTF8String);
NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);
uint8_t * val = nullptr;
CHIP_ERROR err = reader.DupBytes(val, expectedLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, val != nullptr);
if (val != nullptr)
{
NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen) == 0);
}
chip::Platform::MemoryFree(val);
}
void TestBufferContents(nlTestSuite * inSuite, const System::PacketBufferHandle & buffer, const uint8_t * expectedVal,
uint32_t expectedLen)
{
System::PacketBufferHandle buf = buffer.Retain();
while (!buf.IsNull())
{
uint16_t len = buf->DataLength();
NL_TEST_ASSERT(inSuite, len <= expectedLen);
NL_TEST_ASSERT(inSuite, memcmp(buf->Start(), expectedVal, len) == 0);
expectedVal += len;
expectedLen -= len;
buf.Advance();
}
NL_TEST_ASSERT(inSuite, expectedLen == 0);
}
// clang-format off
static const uint8_t Encoding1[] =
{
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00, 0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00, 0x88, 0x02,
0x00, 0x36, 0x00, 0x00, 0x2A, 0x00, 0xEF, 0x02, 0xF0, 0x67, 0xFD, 0xFF, 0x07, 0x00, 0x90, 0x2F,
0x50, 0x09, 0x00, 0x00, 0x00, 0x15, 0x18, 0x17, 0xD4, 0xBB, 0xAA, 0xDD, 0xCC, 0x11, 0x00, 0xB4,
0xA0, 0xBB, 0x0D, 0x00, 0x14, 0xB5, 0x00, 0x28, 0x6B, 0xEE, 0x6D, 0x70, 0x11, 0x01, 0x00, 0x0E,
0x01, 0x53, 0x54, 0x41, 0x52, 0x54, 0x2E, 0x2E, 0x2E, 0x21, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x40, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x23, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x25, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x5E, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x26, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x2A, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x28, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x29, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x2D, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x3D, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x5B, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x5D, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x3B, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x27, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x2E, 0x2E, 0x2E, 0x45, 0x4E, 0x44, 0x18,
0x18, 0x18, 0xCC, 0xBB, 0xAA, 0xDD, 0xCC, 0x05, 0x00, 0x0E, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69,
0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x8A, 0xFF, 0xFF, 0x33, 0x33, 0x8F, 0x41, 0xAB,
0x00, 0x00, 0x01, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x31, 0x40, 0x18
};
// clang-format on
// clang-format off
static const uint8_t Encoding1_DataMacro [] =
{
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 1)),
CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
CHIP_TLV_ARRAY(CHIP_TLV_TAG_CONTEXT_SPECIFIC(0)),
CHIP_TLV_INT8(CHIP_TLV_TAG_ANONYMOUS, 42),
CHIP_TLV_INT8(CHIP_TLV_TAG_ANONYMOUS, -17),
CHIP_TLV_INT32(CHIP_TLV_TAG_ANONYMOUS, -170000),
CHIP_TLV_UINT64(CHIP_TLV_TAG_ANONYMOUS, 40000000000ULL),
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_ANONYMOUS),
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_LIST(CHIP_TLV_TAG_ANONYMOUS),
CHIP_TLV_NULL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 17)),
CHIP_TLV_NULL(CHIP_TLV_TAG_IMPLICIT_PROFILE_4Bytes(900000)),
CHIP_TLV_NULL(CHIP_TLV_TAG_ANONYMOUS),
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_IMPLICIT_PROFILE_4Bytes(4000000000ULL)),
CHIP_TLV_UTF8_STRING_2ByteLength(CHIP_TLV_TAG_COMMON_PROFILE_4Bytes(70000), sizeof(sLargeString) - 1,
'S', 'T', 'A', 'R', 'T', '.', '.', '.',
'!', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '@',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '#', '1',
'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '$', '1', '2',
'3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '%', '1', '2', '3',
'4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '^', '1', '2', '3', '4',
'5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '&', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '*', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'0', '1', '2', '3', '4', '5', '6', '7', '(', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0',
'1', '2', '3', '4', '5', '6', '7', ')', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1',
'2', '3', '4', '5', '6', '7', '-', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2',
'3', '4', '5', '6', '7', '=', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3',
'4', '5', '6', '7', '[', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4',
'5', '6', '7', ']', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5',
'6', '7', ';', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5', '6',
'7', '\'', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'.', '.', '.', 'E', 'N', 'D'),
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_UTF8_STRING_1ByteLength(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 5), sizeof("This is a test") - 1,
'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't'),
CHIP_TLV_FLOAT32(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(65535),
0x33, 0x33, 0x8f, 0x41), // (float)17.9
CHIP_TLV_FLOAT64(CHIP_TLV_TAG_IMPLICIT_PROFILE_4Bytes(65536),
0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x31, 0x40), // (double)17.9
CHIP_TLV_END_OF_CONTAINER
};
// clang-format on
static CHIP_ERROR WriteIntMinMax(nlTestSuite * inSuite, TLVWriter & writer)
{
CHIP_ERROR err;
err = writer.Put(AnonymousTag(), static_cast<int8_t>(INT8_MIN));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int8_t>(INT8_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int16_t>(INT16_MIN));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int16_t>(INT16_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int32_t>(INT32_MIN));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int32_t>(INT32_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int64_t>(INT64_MIN));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<int64_t>(INT64_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<uint8_t>(UINT8_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<uint16_t>(UINT16_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<uint32_t>(UINT32_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(AnonymousTag(), static_cast<uint64_t>(UINT64_MAX));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
return err;
}
static void CheckIntMinMax(nlTestSuite * inSuite, TLVReader & reader)
{
// Writer did Put(AnonymousTag(), static_cast<int8_t>(INT8_MIN))
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(INT8_MIN));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(INT8_MIN));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(INT8_MIN));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT8_MIN));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int8_t>(INT8_MAX))
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(INT8_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(INT8_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(INT8_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT8_MAX));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int16_t>(INT16_MIN))
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(INT16_MIN));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(INT16_MIN));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT16_MIN));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int16_t>(INT16_MAX))
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(INT16_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(INT16_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT16_MAX));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int32_t>(INT32_MIN))
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(INT32_MIN));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT32_MIN));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int32_t>(INT32_MAX))
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(INT32_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT32_MAX));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int64_t>(INT64_MIN))
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT64_MIN));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<int64_t>(INT64_MAX))
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(INT64_MAX));
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<uint8_t>(UINT8_MAX))
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint8_t>(UINT8_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint16_t>(UINT8_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint32_t>(UINT8_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint64_t>(UINT8_MAX));
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<uint16_t>(UINT16_MAX))
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint16_t>(UINT16_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint32_t>(UINT16_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint64_t>(UINT16_MAX));
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<uint32_t>(UINT32_MAX))
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint32_t>(UINT32_MAX));
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint64_t>(UINT32_MAX));
TestNext<TLVReader>(inSuite, reader);
// Writer did Put(AnonymousTag(), static_cast<uint64_t>(UINT64_MAX))
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int8_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int16_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int32_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int64_t>(0), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint8_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint16_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint32_t>(0), CHIP_ERROR_INVALID_INTEGER_VALUE);
TEST_GET_NOERROR(inSuite, reader, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint64_t>(UINT64_MAX));
}
void WriteEncoding1(nlTestSuite * inSuite, TLVWriter & writer)
{
CHIP_ERROR err;
TLVWriter writer2;
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
TLVWriter writer3;
err = writer2.OpenContainer(ContextTag(0), kTLVType_Array, writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// TODO(#1306): expand coverage of inttype encoding tests.
err = writer3.Put(AnonymousTag(), static_cast<int32_t>(42));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int32_t>(-17));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int32_t>(-170000));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<uint64_t>(40000000000ULL));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
TLVWriter writer4;
err = writer3.OpenContainer(AnonymousTag(), kTLVType_Structure, writer4);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.CloseContainer(writer4);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
{
TLVWriter writer5;
err = writer3.OpenContainer(AnonymousTag(), kTLVType_List, writer5);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer5.PutNull(ProfileTag(TestProfile_1, 17));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer5.PutNull(ProfileTag(TestProfile_2, 900000));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer5.PutNull(AnonymousTag());
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
TLVType outerContainerType;
err = writer5.StartContainer(ProfileTag(TestProfile_2, 4000000000ULL), kTLVType_Structure, outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer5.PutString(CommonTag(70000), sLargeString);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer5.EndContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer3.CloseContainer(writer5);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer2.CloseContainer(writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer2.PutString(ProfileTag(TestProfile_1, 5), "This is a test");
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(ProfileTag(TestProfile_2, 65535), static_cast<float>(17.9));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(ProfileTag(TestProfile_2, 65536), 17.9);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
void WriteEmptyEncoding(nlTestSuite * inSuite, TLVWriter & writer)
{
CHIP_ERROR err;
TLVWriter writer2;
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
TLVWriter writer3;
err = writer2.OpenContainer(ProfileTag(TestProfile_1, 256), kTLVType_Array, writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.CloseContainer(writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
void ReadEncoding1(nlTestSuite * inSuite, TLVReader & reader)
{
TestNext<TLVReader>(inSuite, reader);
{
TLVReader reader2;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader2);
{
TLVReader reader3;
TestAndOpenContainer(inSuite, reader2, kTLVType_Array, ContextTag(0), reader3);
TestNext<TLVReader>(inSuite, reader3);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(42));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(42));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(42));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(42));
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint8_t>(42), CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint16_t>(42),
CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(42),
CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(42),
CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader3);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(-17));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(-17));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(-17));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(-17));
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(-17),
CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader3);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(-170000));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(-170000));
TestNext<TLVReader>(inSuite, reader3);
TEST_GET(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int64_t>(40000000000ULL),
CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint64_t>(40000000000ULL));
TestNext<TLVReader>(inSuite, reader3);
{
TLVReader reader4;
TestAndOpenContainer(inSuite, reader3, kTLVType_Structure, AnonymousTag(), reader4);
TestEndAndCloseContainer(inSuite, reader3, reader4);
}
TestNext<TLVReader>(inSuite, reader3);
{
TLVReader reader5;
TestAndOpenContainer(inSuite, reader3, kTLVType_List, AnonymousTag(), reader5);
TestNext<TLVReader>(inSuite, reader5);
TestNull(inSuite, reader5, ProfileTag(TestProfile_1, 17));
TestNext<TLVReader>(inSuite, reader5);
TestNull(inSuite, reader5, ProfileTag(TestProfile_2, 900000));
TestNext<TLVReader>(inSuite, reader5);
TestNull(inSuite, reader5, AnonymousTag());
TestNext<TLVReader>(inSuite, reader5);
{
TLVType outerContainerType;
TestAndEnterContainer<TLVReader>(inSuite, reader5, kTLVType_Structure, ProfileTag(TestProfile_2, 4000000000ULL),
outerContainerType);
TestNext<TLVReader>(inSuite, reader5);
TestString(inSuite, reader5, CommonTag(70000), sLargeString);
TestEndAndExitContainer<TLVReader>(inSuite, reader5, outerContainerType);
}
TestEndAndCloseContainer(inSuite, reader3, reader5);
}
TestEndAndCloseContainer(inSuite, reader2, reader3);
}
TestNext<TLVReader>(inSuite, reader2);
TestString(inSuite, reader2, ProfileTag(TestProfile_1, 5), "This is a test");
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), 17.9f);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535),
static_cast<double>(17.9f));
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), 17.9);
TestEndAndCloseContainer(inSuite, reader, reader2);
}
TestEnd<TLVReader>(inSuite, reader);
}
void WriteEncoding2(nlTestSuite * inSuite, TLVWriter & writer)
{
CHIP_ERROR err;
{ // Container 1
TLVWriter writer1;
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.CloseContainer(writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
{ // Container 2
TLVWriter writer1;
err = writer.OpenContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.CloseContainer(writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
void WriteEncoding3(nlTestSuite * inSuite, TLVWriter & writer)
{
CHIP_ERROR err;
{ // Container 1
TLVWriter writer1;
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
if (err != CHIP_NO_ERROR)
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.CloseContainer(writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
void ReadEncoding3(nlTestSuite * inSuite, TLVReader & reader)
{
TLVReader reader2;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestEndAndCloseContainer(inSuite, reader, reader2);
}
// clang-format off
static const uint8_t Encoding5_DataMacro [] =
{
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 1)),
CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), false),
CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), true),
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 1)),
CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(1)),
CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_END_OF_CONTAINER,
CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(1)),
CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
CHIP_TLV_END_OF_CONTAINER,
};
// clang-format on
void WriteEncoding5(nlTestSuite * inSuite, TLVWriter & writer)
{
CHIP_ERROR err;
{ // Container 1
TLVWriter writer1;
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{ // Inner Container 1
TLVWriter writer2;
err = writer1.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
{ // Inner Container 2
TLVWriter writer2;
err = writer1.OpenContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.CloseContainer(writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
{ // Container 2
TLVWriter writer1;
err = writer.OpenContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.CloseContainer(writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
/**
* AppendEncoding2()
*
* This function appends two boolean types and two container types to the first
* container.
*
* The boolean types are-
* <TestProfile_1, 2, false>
* <TestProfile_2, 2, true>
*
* The two new container types are-
* <TestProfile_1, 1, kTLVType_Structure, <TestProfile_1, 2, true> <TestProfile_2, 2, false> >,
* <TestProfile_2, 1, kTLVType_Structure, <TestProfile_2, 2, false> <TestProfile_1, 2, true> >
*/
void AppendEncoding2(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
{
CHIP_ERROR err;
TLVUpdater updater;
err = updater.Init(buf, dataLen, maxLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updater.SetImplicitProfileId(TestProfile_2);
TestNext<TLVUpdater>(inSuite, updater);
{
TLVType outerContainerType;
TestAndEnterContainer<TLVUpdater>(inSuite, updater, kTLVType_Structure, ProfileTag(TestProfile_1, 1), outerContainerType);
TestNext<TLVUpdater>(inSuite, updater);
// Move the element without modification
TestMove(inSuite, updater);
TestNext<TLVUpdater>(inSuite, updater);
// Read and copy the element with/without modification
TEST_GET_NOERROR(inSuite, updater, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// TestEnd and add data at the end of the container
TestEnd<TLVUpdater>(inSuite, updater);
// Put new values in the encoding using the updater
// Add <TestProfile_1, 2, false>
err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_2, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add a new container
{
TLVType outerContainerType1;
err = updater.StartContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Close the container
err = updater.EndContainer(outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
// Add another new container
{
TLVType outerContainerType1;
err = updater.StartContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_2, 2, false>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Close the container
err = updater.EndContainer(outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
TestEndAndExitContainer<TLVUpdater>(inSuite, updater, outerContainerType);
}
TestNext<TLVUpdater>(inSuite, updater);
// Move the container unmodified
TestMove(inSuite, updater);
TestEnd<TLVUpdater>(inSuite, updater);
err = updater.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updatedLen = updater.GetLengthWritten();
}
/**
* FindAppendEncoding2()
*
* This function appends two boolean types and two container types to the first
* container. It is very similar to AppendEncoding2() above except for the fact
* that it uses TLVUtilities::Find() to find the element of interest before
* appending new data.
*
* The boolean types are-
* <TestProfile_1, 2, false>
* <TestProfile_2, 2, true>
*
* The two new container types are-
* <TestProfile_1, 1, kTLVType_Structure, <TestProfile_1, 2, true> <TestProfile_2, 2, false> >,
* <TestProfile_2, 1, kTLVType_Structure, <TestProfile_2, 2, false> <TestProfile_1, 2, true> >
*/
void FindAppendEncoding2(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen,
bool findContainer)
{
CHIP_ERROR err;
TLVReader reader;
TLVUpdater updater;
// Initialize a reader
reader.Init(buf, dataLen);
reader.ImplicitProfileId = TestProfile_2;
if (findContainer)
{
// Find the container
TLVReader tagReader;
TLVType outerContainerType;
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_1, 1), tagReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = tagReader.EnterContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
do
{
err = tagReader.Next();
} while (err != CHIP_END_OF_TLV);
TestEnd<TLVReader>(inSuite, tagReader);
// Init a TLVUpdater using the TLVReader
err = updater.Init(tagReader, maxLen - dataLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
else
{
// Find
TLVReader tagReader;
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 2), tagReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Test Find(recurse = true)
TLVReader tagReader2;
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 2), tagReader2, true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
//
// Test Find(recurse = false)
TLVReader tagReader3;
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 2), tagReader3, false);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_TAG_NOT_FOUND);
// Init a TLVUpdater using the TLVReader
err = updater.Init(tagReader, maxLen - dataLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
TestNext<TLVUpdater>(inSuite, updater);
// Move the element without modification
TestMove(inSuite, updater);
}
// Put new values in the encoding using the updater
// Add <TestProfile_1, 2, false>
err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_2, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add a new container
{
TLVType outerContainerType1;
err = updater.StartContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Close the container
err = updater.EndContainer(outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
// Add another new container
{
TLVType outerContainerType1;
err = updater.StartContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_2, 2, false>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Close the container
err = updater.EndContainer(outerContainerType1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
// Move everything else unmodified
updater.MoveUntilEnd();
TestEnd<TLVUpdater>(inSuite, updater);
err = updater.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updatedLen = updater.GetLengthWritten();
}
void AppendEncoding3(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
{
CHIP_ERROR err;
TLVUpdater updater;
err = updater.Init(buf, dataLen, maxLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updater.SetImplicitProfileId(TestProfile_2);
TestNext<TLVUpdater>(inSuite, updater);
{
TLVType outerContainerType;
TestAndEnterContainer<TLVUpdater>(inSuite, updater, kTLVType_Structure, ProfileTag(TestProfile_1, 1), outerContainerType);
TestNext<TLVUpdater>(inSuite, updater);
// Move the element without modification
TestMove(inSuite, updater);
// Put new value in the encoding using the updater
// Add <TestProfile_2, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
TestEndAndExitContainer<TLVUpdater>(inSuite, updater, outerContainerType);
}
TestEnd<TLVUpdater>(inSuite, updater);
err = updater.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updatedLen = updater.GetLengthWritten();
}
void AppendEncoding4(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
{
CHIP_ERROR err;
TLVUpdater updater;
err = updater.Init(buf, dataLen, maxLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updater.SetImplicitProfileId(TestProfile_2);
// Add a new container
{
TLVType outerContainerType;
err = updater.StartContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Add <TestProfile_1, 2, true>
err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Close the container
err = updater.EndContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = updater.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updatedLen = updater.GetLengthWritten();
}
void DeleteEncoding5(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
{
CHIP_ERROR err;
TLVUpdater updater;
err = updater.Init(buf, dataLen, maxLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updater.SetImplicitProfileId(TestProfile_2);
TestNext<TLVUpdater>(inSuite, updater);
{
TLVType outerContainerType;
TestAndEnterContainer<TLVUpdater>(inSuite, updater, kTLVType_Structure, ProfileTag(TestProfile_1, 1), outerContainerType);
TestNext<TLVUpdater>(inSuite, updater);
TestMove(inSuite, updater);
TestNext<TLVUpdater>(inSuite, updater);
TestMove(inSuite, updater);
TestNext<TLVUpdater>(inSuite, updater);
// Get the value to inspect and skip writing it
TEST_GET_NOERROR(inSuite, updater, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
TestNext<TLVUpdater>(inSuite, updater);
// Skip the next boolean type and don't copy by doing nothing
TestNext<TLVUpdater>(inSuite, updater);
// Read ahead into the next container and decide whether to skip or
// not based on elements in the container
{
TLVReader reader;
TLVType containerType;
updater.GetReader(reader);
TestAndEnterContainer<TLVReader>(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), containerType);
TestNext<TLVReader>(inSuite, reader);
// If the container's first element has the tag <TestProfile_1, 2>
// skip the whole container, and if NOT copy the container
if (reader.GetTag() != ProfileTag(TestProfile_1, 2))
TestMove(inSuite, updater);
}
TestNext<TLVUpdater>(inSuite, updater);
// Skip the next container and don't copy by doing nothing
TestEndAndExitContainer<TLVUpdater>(inSuite, updater, outerContainerType);
}
// Move everything else unmodified
updater.MoveUntilEnd();
TestEnd<TLVUpdater>(inSuite, updater);
err = updater.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
updatedLen = updater.GetLengthWritten();
}
void ReadAppendedEncoding2(nlTestSuite * inSuite, TLVReader & reader)
{
TestNext<TLVReader>(inSuite, reader);
{ // Container 1
TLVReader reader1;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), true);
TestNext<TLVReader>(inSuite, reader1);
{
TLVReader reader2;
TestAndOpenContainer(inSuite, reader1, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestEndAndCloseContainer(inSuite, reader1, reader2);
}
TestNext<TLVReader>(inSuite, reader1);
{
TLVReader reader2;
TestAndOpenContainer(inSuite, reader1, kTLVType_Structure, ProfileTag(TestProfile_2, 1), reader2);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestEndAndCloseContainer(inSuite, reader1, reader2);
}
TestEndAndCloseContainer(inSuite, reader, reader1);
}
TestNext<TLVReader>(inSuite, reader);
{ // Container 2
TLVReader reader1;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_2, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestEndAndCloseContainer(inSuite, reader, reader1);
}
TestEnd<TLVReader>(inSuite, reader);
}
void ReadAppendedEncoding3(nlTestSuite * inSuite, TLVReader & reader)
{
TestNext<TLVReader>(inSuite, reader);
{ // Container 1
TLVReader reader1;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), true);
TestEndAndCloseContainer(inSuite, reader, reader1);
}
TestEnd<TLVReader>(inSuite, reader);
}
void ReadAppendedEncoding4(nlTestSuite * inSuite, TLVReader & reader)
{
TestNext<TLVReader>(inSuite, reader);
{ // Container 1
TLVReader reader1;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestEndAndCloseContainer(inSuite, reader, reader1);
}
TestEnd<TLVReader>(inSuite, reader);
}
void ReadDeletedEncoding5(nlTestSuite * inSuite, TLVReader & reader)
{
TestNext<TLVReader>(inSuite, reader);
{ // Container 1
TLVReader reader1;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestEndAndCloseContainer(inSuite, reader, reader1);
}
TestNext<TLVReader>(inSuite, reader);
{ // Container 2
TLVReader reader1;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_2, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader1);
TEST_GET_NOERROR(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestEndAndCloseContainer(inSuite, reader, reader1);
}
TestEnd<TLVReader>(inSuite, reader);
}
/**
* Test Simple Write and Reader
*/
void CheckSimpleWriteRead(nlTestSuite * inSuite, void * inContext)
{
uint8_t buf[2048];
TLVWriter writer;
TLVReader reader;
uint32_t remainingFreedLen;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
remainingFreedLen = writer.GetRemainingFreeLength();
NL_TEST_ASSERT(inSuite, sizeof(buf) == remainingFreedLen);
WriteEncoding1(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
#ifdef DUMP_ENCODING
for (uint32_t i = 0; i < encodedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding1, encodedLen) == 0);
reader.Init(buf, encodedLen);
reader.ImplicitProfileId = TestProfile_2;
ReadEncoding1(inSuite, reader);
}
static void TestIntMinMax(nlTestSuite * inSuite, void * inContext)
{
CHIP_ERROR err;
uint8_t buf[2048];
TLVWriter writer, writer1;
TLVReader reader, reader1;
writer.Init(buf, sizeof(buf));
writer.ImplicitProfileId = TestProfile_3;
err = writer.OpenContainer(ProfileTag(TestProfile_3, 1), kTLVType_Array, writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
WriteIntMinMax(inSuite, writer1);
err = writer.CloseContainer(writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(buf, sizeof(buf));
reader.ImplicitProfileId = TestProfile_3;
TestNext<TLVReader>(inSuite, reader);
TestAndOpenContainer(inSuite, reader, kTLVType_Array, ProfileTag(TestProfile_3, 1), reader1);
TestNext<TLVReader>(inSuite, reader1);
CheckIntMinMax(inSuite, reader1);
TestEndAndCloseContainer(inSuite, reader, reader1);
}
/**
* Log the specified message in the form of @a aFormat.
*
* @param[in] aFormat A pointer to a NULL-terminated C string with
* C Standard Library-style format specifiers
* containing the log message to be formatted and
* logged.
* @param[in] ... An argument list whose elements should correspond
* to the format specifiers in @a aFormat.
*
*/
void ENFORCE_FORMAT(1, 2) SimpleDumpWriter(const char * aFormat, ...)
{
va_list args;
va_start(args, aFormat);
vprintf(aFormat, args);
va_end(args);
}
/**
* Test Pretty Printer
*/
void CheckPrettyPrinter(nlTestSuite * inSuite, void * inContext)
{
uint8_t buf[2048];
TLVWriter writer;
TLVReader reader;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding1(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding1, encodedLen) == 0);
reader.Init(buf, encodedLen);
reader.ImplicitProfileId = TestProfile_2;
chip::TLV::Debug::Dump(reader, SimpleDumpWriter);
}
static char gStringDumpWriterBuf[128] = { 0 };
static size_t gStringDumpWriterLengthWritten = 0;
/**
* Log the specified message in the form of @a aFormat.
*
* @param[in] aFormat A pointer to a NULL-terminated C string with
* C Standard Library-style format specifiers
* containing the log message to be formatted and
* logged.
* @param[in] ... An argument list whose elements should correspond
* to the format specifiers in @a aFormat.
*
*/
void ENFORCE_FORMAT(1, 2) StringDumpWriter(const char * aFormat, ...)
{
va_list args;
va_start(args, aFormat);
gStringDumpWriterLengthWritten +=
static_cast<size_t>(vsprintf(&gStringDumpWriterBuf[gStringDumpWriterLengthWritten], aFormat, args));
va_end(args);
}
/**
* Test Octet String Pretty Printer
*/
void CheckOctetStringPrettyPrinter(nlTestSuite * inSuite, void * inContext)
{
const uint8_t testOctetString[] = { 0x62, 0xFA, 0x82, 0x33, 0x59, 0xAC, 0xFA, 0xA9 };
const char expectedPrint[] =
"0x04, tag[Common Profile (2 Bytes)]: 0x0::0x0::0x0, type: Octet String (0x10), length: 8, value: hex:62FA823359ACFAA9\n";
uint8_t encodedBuf[128] = { 0 };
TLVWriter writer;
writer.Init(encodedBuf);
NL_TEST_ASSERT_SUCCESS(inSuite, writer.PutBytes(CommonTag(0), testOctetString, sizeof(testOctetString)));
NL_TEST_ASSERT_SUCCESS(inSuite, writer.Finalize());
TLVReader reader;
reader.Init(encodedBuf, writer.GetLengthWritten());
chip::TLV::Debug::Dump(reader, StringDumpWriter);
NL_TEST_ASSERT(inSuite, strlen(expectedPrint) == strlen(gStringDumpWriterBuf));
NL_TEST_ASSERT(inSuite, strcmp(expectedPrint, gStringDumpWriterBuf) == 0);
}
/**
* Test Data Macros
*/
void CheckDataMacro(nlTestSuite * inSuite, void * inContext)
{
NL_TEST_ASSERT(inSuite, sizeof(Encoding1_DataMacro) == sizeof(Encoding1));
NL_TEST_ASSERT(inSuite, memcmp(Encoding1, Encoding1_DataMacro, sizeof(Encoding1)) == 0);
uint8_t buf[2048];
TLVWriter writer;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding5(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, sizeof(Encoding5_DataMacro) == encodedLen);
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding5_DataMacro, encodedLen) == 0);
}
static CHIP_ERROR NullIterateHandler(const TLVReader & aReader, size_t aDepth, void * aContext)
{
(void) aReader;
(void) aDepth;
(void) aContext;
return CHIP_NO_ERROR;
}
static CHIP_ERROR FindContainerWithElement(const TLVReader & aReader, size_t aDepth, void * aContext)
{
TLVReader reader;
TLVReader result;
Tag * tag = static_cast<Tag *>(aContext);
CHIP_ERROR err = CHIP_NO_ERROR;
TLVType containerType;
reader.Init(aReader);
if (TLVTypeIsContainer(reader.GetType()))
{
ReturnErrorOnFailure(reader.EnterContainer(containerType));
err = chip::TLV::Utilities::Find(reader, *tag, result, false);
// Map a successful find (CHIP_NO_ERROR) onto a signal that the element has been found.
if (err == CHIP_NO_ERROR)
{
err = CHIP_ERROR_SENTINEL;
}
// Map a failed find attempt to NO_ERROR
else if (err == CHIP_ERROR_TLV_TAG_NOT_FOUND)
{
err = CHIP_NO_ERROR;
}
}
return err;
}
/**
* Test CHIP TLV Utilities
*/
void CheckCHIPTLVUtilities(nlTestSuite * inSuite, void * inContext)
{
uint8_t buf[2048];
TLVWriter writer;
TLVReader reader, reader1;
CHIP_ERROR err = CHIP_NO_ERROR;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding1(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding1, encodedLen) == 0);
reader.Init(buf, encodedLen);
reader.ImplicitProfileId = TestProfile_2;
reader1.Init(reader);
err = reader1.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Find a tag
TLVReader tagReader;
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 65536), tagReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Find with reader positioned "on" the element of interest
err = chip::TLV::Utilities::Find(reader1, ProfileTag(TestProfile_1, 1), tagReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Find a tag that's not present
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 1024), tagReader);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_TAG_NOT_FOUND);
// Find with a predicate
{
uint8_t buf1[74];
writer.Init(buf1);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding2(inSuite, writer);
// Initialize a reader
reader1.Init(buf1, writer.GetLengthWritten());
reader1.ImplicitProfileId = TestProfile_2;
// position the reader on the first element
reader1.Next();
Tag tag = ProfileTag(TestProfile_1, 1);
err = chip::TLV::Utilities::Find(reader1, FindContainerWithElement, &tag, tagReader, false);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_TAG_NOT_FOUND);
tag = ProfileTag(TestProfile_2, 2);
err = chip::TLV::Utilities::Find(reader1, FindContainerWithElement, &tag, tagReader, false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, tagReader.GetType() == kTLVType_Structure);
NL_TEST_ASSERT(inSuite, tagReader.GetTag() == ProfileTag(TestProfile_1, 1));
// Position the reader on the second element
reader1.Next();
err = chip::TLV::Utilities::Find(reader1, FindContainerWithElement, &tag, tagReader, false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, tagReader.GetType() == kTLVType_Structure);
NL_TEST_ASSERT(inSuite, tagReader.GetTag() == ProfileTag(TestProfile_2, 1));
}
// Count
size_t count;
const size_t expectedCount = 18;
reader1.Init(reader);
reader1.Next();
err = chip::TLV::Utilities::Count(reader, count);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, count == expectedCount);
// Count with reader already positioned "on" the first element in the encoding
err = chip::TLV::Utilities::Count(reader1, count);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, count == expectedCount);
// Iterate
err = chip::TLV::Utilities::Iterate(reader, NullIterateHandler, nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
}
/**
* Test CHIP TLV Empty Find
*/
void CheckCHIPTLVEmptyFind(nlTestSuite * inSuite, void * inContext)
{
uint8_t buf[30];
TLVWriter writer;
TLVReader reader;
CHIP_ERROR err = CHIP_NO_ERROR;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEmptyEncoding(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
reader.Init(buf, encodedLen);
reader.ImplicitProfileId = TestProfile_2;
// Find the empty container
TLVReader tagReader;
err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_1, 256), tagReader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
// clang-format off
uint8_t Encoding2[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x88, 0x02, 0x00,
0x18,
// Container 2
0x95, 0x01, 0x00,
0x88, 0x02, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x18
};
uint8_t AppendedEncoding2[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x88, 0x02, 0x00,
0xC8, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x89, 0x02, 0x00,
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x88, 0x02, 0x00,
0x18,
0x95, 0x01, 0x00,
0x88, 0x02, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x18,
0x18,
// Container 2
0x95, 0x01, 0x00,
0x88, 0x02, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x18
};
// clang-format on
void WriteAppendReadTest0(nlTestSuite * inSuite)
{
uint8_t buf[74];
uint32_t updatedLen;
TLVWriter writer;
TLVReader reader;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding2(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
#ifdef DUMP_ENCODING
printf("Initial encoding:\n");
for (uint32_t i = 0; i < encodedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding2));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding2, encodedLen) == 0);
// Append new data into encoding
AppendEncoding2(inSuite, buf, encodedLen, sizeof(buf), updatedLen);
#ifdef DUMP_ENCODING
printf("Updated encoding:\n");
for (uint32_t i = 0; i < updatedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding2));
NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding2, updatedLen) == 0);
reader.Init(buf, updatedLen);
reader.ImplicitProfileId = TestProfile_2;
ReadAppendedEncoding2(inSuite, reader);
}
void WriteFindAppendReadTest(nlTestSuite * inSuite, bool findContainer)
{
uint8_t buf[74];
uint32_t updatedLen;
TLVWriter writer;
TLVReader reader;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding2(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
#ifdef DUMP_ENCODING
printf("Initial encoding:\n");
for (uint32_t i = 0; i < encodedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding2));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding2, encodedLen) == 0);
// Append new data into encoding
FindAppendEncoding2(inSuite, buf, encodedLen, sizeof(buf), updatedLen, findContainer);
#ifdef DUMP_ENCODING
printf("Updated encoding:\n");
for (uint32_t i = 0; i < updatedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding2));
NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding2, updatedLen) == 0);
reader.Init(buf, updatedLen);
reader.ImplicitProfileId = TestProfile_2;
ReadAppendedEncoding2(inSuite, reader);
}
// clang-format off
uint8_t Encoding3[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0x88, 0x02, 0x00,
0x18,
};
uint8_t AppendedEncoding3[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0x88, 0x02, 0x00,
0x89, 0x02, 0x00,
0x18
};
// clang-format on
void WriteAppendReadTest1(nlTestSuite * inSuite)
{
uint8_t buf[14];
uint32_t updatedLen;
TLVWriter writer;
TLVReader reader;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding3(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
#ifdef DUMP_ENCODING
printf("Initial encoding:\n");
for (uint32_t i = 0; i < encodedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding3));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding3, encodedLen) == 0);
// Append new data into encoding
AppendEncoding3(inSuite, buf, encodedLen, sizeof(buf), updatedLen);
#ifdef DUMP_ENCODING
printf("Updated encoding:\n");
for (uint32_t i = 0; i < updatedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding3));
NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding3, updatedLen) == 0);
reader.Init(buf, updatedLen);
reader.ImplicitProfileId = TestProfile_2;
ReadAppendedEncoding3(inSuite, reader);
}
// clang-format off
uint8_t AppendedEncoding4[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0x88, 0x02, 0x00,
0x18,
};
// clang-format on
void AppendReadTest(nlTestSuite * inSuite)
{
uint8_t buf[11];
uint32_t updatedLen;
memset(buf, 0, sizeof(buf));
#ifdef DUMP_ENCODING
printf("Initial encoding:\n");
for (uint32_t i = 0; i < sizeof(buf); i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
// Append new data to encoding
AppendEncoding4(inSuite, buf, 0, sizeof(buf), updatedLen);
#ifdef DUMP_ENCODING
printf("Updated encoding:\n");
for (uint32_t i = 0; i < updatedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding4));
NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding4, updatedLen) == 0);
TLVReader reader;
reader.Init(buf, updatedLen);
reader.ImplicitProfileId = TestProfile_2;
ReadAppendedEncoding4(inSuite, reader);
}
// clang-format off
uint8_t Encoding5[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x88, 0x02, 0x00,
0xC8, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x89, 0x02, 0x00,
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x88, 0x02, 0x00,
0x18,
0x95, 0x01, 0x00,
0x88, 0x02, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x18,
0x18,
// Container 2
0x95, 0x01, 0x00,
0x88, 0x02, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x18
};
uint8_t DeletedEncoding5[] =
{
// Container 1
0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x88, 0x02, 0x00,
0x18,
// Container 2
0x95, 0x01, 0x00,
0x88, 0x02, 0x00,
0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
0x18
};
// clang-format on
void WriteDeleteReadTest(nlTestSuite * inSuite)
{
uint8_t buf[74];
uint32_t updatedLen;
TLVWriter writer;
TLVReader reader;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding5(inSuite, writer);
uint32_t encodedLen = writer.GetLengthWritten();
#ifdef DUMP_ENCODING
for (uint32_t i = 0; i < encodedLen; i++)
{
if (i != 0 && i % 16 == 0)
printf("\n");
printf("0x%02X, ", buf[i]);
}
printf("\n");
#endif
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding5));
NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding5, encodedLen) == 0);
// Delete some elements from the encoding
DeleteEncoding5(inSuite, buf, encodedLen, sizeof(buf), updatedLen);
NL_TEST_ASSERT(inSuite, updatedLen == sizeof(DeletedEncoding5));
NL_TEST_ASSERT(inSuite, memcmp(buf, DeletedEncoding5, updatedLen) == 0);
reader.Init(buf, updatedLen);
reader.ImplicitProfileId = TestProfile_2;
ReadDeletedEncoding5(inSuite, reader);
}
/**
* Test Packet Buffer
*/
void CheckPacketBuffer(nlTestSuite * inSuite, void * inContext)
{
System::PacketBufferHandle buf = System::PacketBufferHandle::New(sizeof(Encoding1), 0);
System::PacketBufferTLVWriter writer;
System::PacketBufferTLVReader reader;
writer.Init(buf.Retain());
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding1(inSuite, writer);
TestBufferContents(inSuite, buf, Encoding1, sizeof(Encoding1));
reader.Init(buf.Retain());
reader.ImplicitProfileId = TestProfile_2;
ReadEncoding1(inSuite, reader);
reader.Init(buf.Retain());
reader.ImplicitProfileId = TestProfile_2;
ReadEncoding1(inSuite, reader);
}
CHIP_ERROR CountEvictedMembers(CHIPCircularTLVBuffer & inBuffer, void * inAppData, TLVReader & inReader)
{
TestTLVContext * context = static_cast<TestTLVContext *>(inAppData);
CHIP_ERROR err;
// "Process" the first element in the reader
err = inReader.Next();
NL_TEST_ASSERT(context->mSuite, err == CHIP_NO_ERROR);
err = inReader.Skip();
NL_TEST_ASSERT(context->mSuite, err == CHIP_NO_ERROR);
context->mEvictionCount++;
context->mEvictedBytes += inReader.GetLengthRead();
return CHIP_NO_ERROR;
}
void CheckCircularTLVBufferSimple(nlTestSuite * inSuite, void * inContext)
{
// Write 40 bytes as 4 separate events into a 30 byte buffer. On
// completion of the test, the buffer should contain 2 elements
// and 2 elements should have been evicted in the last call to
// WriteEncoding.
uint8_t backingStore[30];
CircularTLVWriter writer;
CircularTLVReader reader;
TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
CHIPCircularTLVBuffer buffer(backingStore, 30);
writer.Init(buffer);
writer.ImplicitProfileId = TestProfile_2;
context->mEvictionCount = 0;
context->mEvictedBytes = 0;
buffer.mProcessEvictedElement = CountEvictedMembers;
buffer.mAppData = inContext;
writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
NL_TEST_ASSERT(inSuite, context->mEvictionCount == 2);
NL_TEST_ASSERT(inSuite, context->mEvictedBytes == 18);
NL_TEST_ASSERT(inSuite, buffer.DataLength() == 22);
NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten());
// At this point the buffer should contain 2 instances of Encoding3.
reader.Init(buffer);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
ReadEncoding3(inSuite, reader);
TestNext<TLVReader>(inSuite, reader);
ReadEncoding3(inSuite, reader);
// Check that the reader is out of data
TestEnd<TLVReader>(inSuite, reader);
}
void CheckCircularTLVBufferStartMidway(nlTestSuite * inSuite, void * inContext)
{
// Write 40 bytes as 4 separate events into a 30 byte buffer. On
// completion of the test, the buffer should contain 2 elements
// and 2 elements should have been evicted in the last call to
// WriteEncoding.
uint8_t backingStore[30];
CircularTLVWriter writer;
CircularTLVReader reader;
TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
CHIPCircularTLVBuffer buffer(backingStore, 30, &(backingStore[15]));
writer.Init(buffer);
writer.ImplicitProfileId = TestProfile_2;
context->mEvictionCount = 0;
context->mEvictedBytes = 0;
buffer.mProcessEvictedElement = CountEvictedMembers;
buffer.mAppData = inContext;
writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
NL_TEST_ASSERT(inSuite, context->mEvictionCount == 2);
NL_TEST_ASSERT(inSuite, context->mEvictedBytes == 18);
NL_TEST_ASSERT(inSuite, buffer.DataLength() == 22);
NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten());
// At this point the buffer should contain 2 instances of Encoding3.
reader.Init(buffer);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
ReadEncoding3(inSuite, reader);
TestNext<TLVReader>(inSuite, reader);
ReadEncoding3(inSuite, reader);
// Check that the reader is out of data
TestEnd<TLVReader>(inSuite, reader);
}
void CheckCircularTLVBufferEvictStraddlingEvent(nlTestSuite * inSuite, void * inContext)
{
// Write 95 bytes to the buffer as 9 different TLV elements: 1
// 7-byte element and 8 11-byte elements.
// On completion of the test, the buffer should contain 2 elements
// and 7 elements should have been evicted in the last call to
// WriteEncoding.
TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
uint8_t backingStore[30];
CircularTLVWriter writer;
CircularTLVReader reader;
CHIPCircularTLVBuffer buffer(backingStore, 30);
writer.Init(buffer);
writer.ImplicitProfileId = TestProfile_2;
context->mEvictionCount = 0;
context->mEvictedBytes = 0;
buffer.mProcessEvictedElement = CountEvictedMembers;
buffer.mAppData = inContext;
writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
// the write below will evict an element that straddles the buffer boundary.
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
WriteEncoding3(inSuite, writer);
NL_TEST_ASSERT(inSuite,
writer.GetLengthWritten() ==
(8 * 11 + 7)); // 8 writes of Encoding3 (11 bytes each) and 7 bytes for the initial boolean.
NL_TEST_ASSERT(inSuite, buffer.DataLength() == 22);
NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten());
NL_TEST_ASSERT(inSuite, context->mEvictionCount == 7);
// At this point the buffer should contain 2 instances of Encoding3.
reader.Init(buffer);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
ReadEncoding3(inSuite, reader);
TestNext<TLVReader>(inSuite, reader);
ReadEncoding3(inSuite, reader);
// Check that the reader is out of data
TestEnd<TLVReader>(inSuite, reader);
}
void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext)
{
TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
CHIP_ERROR err;
uint8_t backingStore[7];
uint8_t backingStore1[14];
CircularTLVWriter writer;
CircularTLVReader reader;
TLVWriter writer1;
CHIPCircularTLVBuffer buffer(backingStore, sizeof(backingStore));
CHIPCircularTLVBuffer buffer1(backingStore1, sizeof(backingStore1));
writer.Init(buffer);
writer.ImplicitProfileId = TestProfile_2;
context->mEvictionCount = 0;
context->mEvictedBytes = 0;
buffer.mProcessEvictedElement = CountEvictedMembers;
buffer.mAppData = inContext;
// Test eviction for an element that fits in the underlying buffer exactly
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// At this point the buffer should contain only the boolean we just wrote
reader.Init(buffer);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
// Check that the reader is out of data
TestEnd<TLVReader>(inSuite, reader);
// verify that an element larger than the underlying buffer fails out.
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
// Verify reader correctness
// Write an element that takes half of the buffer, and evict it.
// Do it 2 times, so we test what happens when the head is at the
// middle and at the end of the buffer but the buffer is empty.
int i = 0;
for (i = 0; i < 2; i++)
{
writer.Init(buffer1);
writer.ImplicitProfileId = TestProfile_2;
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(buffer1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestEnd<TLVReader>(inSuite, reader);
buffer1.EvictHead();
reader.Init(buffer1);
reader.ImplicitProfileId = TestProfile_2;
TestEnd<TLVReader>(inSuite, reader);
}
writer.Init(buffer1);
writer.ImplicitProfileId = TestProfile_2;
context->mEvictionCount = 0;
context->mEvictedBytes = 0;
buffer1.mProcessEvictedElement = CountEvictedMembers;
buffer1.mAppData = inContext;
// Two elements fit in the buffer exactly
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
// Verify that we can read out two elements from the buffer
reader.Init(buffer1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
TestEnd<TLVReader>(inSuite, reader);
// Check that the eviction works as expected
buffer1.EvictHead();
// At this point the buffer should contain only the second boolean
reader.Init(buffer1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
// Check that the reader is out of data
TestEnd<TLVReader>(inSuite, reader);
// Write another boolean, verify that the buffer is full and contains two booleans
writer.Init(buffer1);
writer.ImplicitProfileId = TestProfile_2;
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Verify that we can read out two elements from the buffer
reader.Init(buffer1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestEnd<TLVReader>(inSuite, reader);
// Evict the elements from the buffer, verfiy that we have an
// empty reader on our hands
buffer1.EvictHead();
buffer1.EvictHead();
reader.Init(buffer1);
reader.ImplicitProfileId = TestProfile_2;
TestEnd<TLVReader>(inSuite, reader);
}
void CheckCHIPTLVPutStringF(nlTestSuite * inSuite, void * inContext)
{
const size_t bufsize = 24;
char strBuffer[bufsize];
char valStr[bufsize];
uint8_t backingStore[bufsize];
TLVWriter writer;
TLVReader reader;
size_t num = 1;
CHIP_ERROR err = CHIP_NO_ERROR;
writer.Init(backingStore, bufsize);
snprintf(strBuffer, sizeof(strBuffer), "Sample string %u", static_cast<unsigned int>(num));
err = writer.PutStringF(ProfileTag(TestProfile_1, 1), "Sample string %u", static_cast<unsigned int>(num));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(backingStore, writer.GetLengthWritten());
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.GetString(valStr, bufsize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, bufsize) == 0);
}
void CheckCHIPTLVPutStringSpan(nlTestSuite * inSuite, void * inContext)
{
const size_t bufsize = 24;
char strBuffer[bufsize] = "Sample string";
char valStr[bufsize];
uint8_t backingStore[bufsize];
TLVWriter writer;
TLVReader reader;
CHIP_ERROR err = CHIP_NO_ERROR;
Span<char> strSpan;
//
// Write a string that has a size that exceeds 32-bits. This is only possible
// on platforms where size_t is bigger than uint32_t.
//
if (sizeof(size_t) > sizeof(uint32_t))
{
writer.Init(backingStore, bufsize);
snprintf(strBuffer, sizeof(strBuffer), "Sample string");
strSpan = { strBuffer, static_cast<size_t>(0xffffffffff) };
err = writer.PutString(ProfileTag(TestProfile_1, 1), strSpan);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
}
{
writer.Init(backingStore, bufsize);
snprintf(strBuffer, sizeof(strBuffer), "Sample string");
strSpan = { strBuffer, strlen("Sample string") };
err = writer.PutString(ProfileTag(TestProfile_1, 1), strSpan);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(backingStore, writer.GetLengthWritten());
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.GetString(valStr, bufsize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, bufsize) == 0);
}
}
void CheckCHIPTLVPutStringFCircular(nlTestSuite * inSuite, void * inContext)
{
const size_t bufsize = 40;
char strBuffer[bufsize];
char valStr[bufsize];
uint8_t backingStore[bufsize];
CircularTLVWriter writer;
CircularTLVReader reader;
CHIPCircularTLVBuffer buffer(backingStore, bufsize);
size_t num = 1;
CHIP_ERROR err = CHIP_NO_ERROR;
// Initial test: Verify that a straight printf works as expected into continuous buffer.
writer.Init(buffer);
snprintf(strBuffer, sizeof(strBuffer), "Sample string %u", static_cast<unsigned int>(num));
err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.PutStringF(ProfileTag(TestProfile_1, 1), "Sample string %u", static_cast<unsigned int>(num));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(buffer);
// Skip over the initial element
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.GetString(valStr, bufsize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, bufsize) == 0);
// Verify that the PutStringF will handle correctly the case with the discontinuous buffer
// This print will both stradle the boundary of the buffer and displace the previous two elements.
num = 2;
snprintf(strBuffer, sizeof(strBuffer), "Sample string %u", static_cast<unsigned int>(num));
err = writer.PutStringF(ProfileTag(TestProfile_1, 1), "Sample string %u", static_cast<unsigned int>(num));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(buffer);
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.GetString(valStr, bufsize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, bufsize) == 0);
}
void CheckCHIPTLVByteSpan(nlTestSuite * inSuite, void * inContext)
{
const size_t bufSize = 14;
uint8_t bytesBuffer[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
uint8_t backingStore[bufSize];
TLVWriter writer;
TLVReader reader;
CHIP_ERROR err = CHIP_NO_ERROR;
writer.Init(backingStore);
ByteSpan writerSpan(bytesBuffer);
err = writer.Put(ProfileTag(TestProfile_1, 1), writerSpan);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(backingStore, writer.GetLengthWritten());
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
chip::ByteSpan readerSpan;
err = reader.Get(readerSpan);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, memcmp(readerSpan.data(), bytesBuffer, sizeof(bytesBuffer)) == 0);
}
void CheckCHIPTLVSkipCircular(nlTestSuite * inSuite, void * inContext)
{
const size_t bufsize = 40; // large enough s.t. 2 elements fit, 3rd causes eviction
uint8_t backingStore[bufsize];
char testString[] = "Sample string"; // 13 characters, without the trailing NULL, add 3 bytes for anon tag
// Any pair of reader and writer would work here, either PacketBuffer based or CircularTLV based.
CircularTLVWriter writer;
CircularTLVReader reader;
CHIPCircularTLVBuffer buffer(backingStore, bufsize);
CHIP_ERROR err = CHIP_NO_ERROR;
writer.Init(buffer);
err = writer.PutString(AnonymousTag(), testString);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.PutString(AnonymousTag(), testString);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.PutString(AnonymousTag(), testString); // This event straddles the boundary
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.PutString(AnonymousTag(), testString); // This one does not.
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
reader.Init(buffer);
err = reader.Next(); // position the reader at the straddling element
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.Skip(); // // Test that the buf ptr is handled correctly within the ReadData() function.
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
/**
* Test Buffer Overflow
*/
void CheckBufferOverflow(nlTestSuite * inSuite, void * inContext)
{
System::PacketBufferTLVReader reader;
System::PacketBufferHandle buf = System::PacketBufferHandle::New(sizeof(Encoding1), 0);
uint16_t maxDataLen = buf->MaxDataLength();
uint16_t reserve = static_cast<uint16_t>((sizeof(Encoding1) < maxDataLen) ? (maxDataLen - sizeof(Encoding1)) + 2 : 0);
// Repeatedly write and read a TLV encoding to a chain of PacketBuffers. Use progressively larger
// and larger amounts of space in the first buffer to force the encoding to overlap the
// end of the buffer and the beginning of the next.
for (; reserve < maxDataLen; reserve++)
{
buf->SetStart(buf->Start() + reserve);
{
System::PacketBufferTLVWriter writer;
// Scope for writer because we want it to go out of scope before we
// mess with the chain after writing is done.
writer.Init(buf.Retain(), /* useChainedBuffers = */ true);
writer.ImplicitProfileId = TestProfile_2;
WriteEncoding1(inSuite, writer);
}
TestBufferContents(inSuite, buf, Encoding1, sizeof(Encoding1));
// Compact the buffer, since we don't allow reading from chained
// buffers.
buf->CompactHead();
reader.Init(buf.Retain());
reader.ImplicitProfileId = TestProfile_2;
ReadEncoding1(inSuite, reader);
buf = System::PacketBufferHandle::New(sizeof(Encoding1), 0);
}
}
/**
* Test case to verify the correctness of TLVReader::GetTag()
*
* TLVReader::GetTag() does not return the correct tag value when the
* the compiler optimization level contains strict aliasing. In the below
* example, the returned tag value would be 0xe, instead of 0xe00000001.
*
* The issue has been spotted on debug builds.
*
*/
// clang-format off
static const uint8_t sIdentifyResponseBuf[] =
{
0xD5, 0x00, 0x00, 0x0E, 0x00, 0x01, 0x00, 0x25,
0x00, 0x5A, 0x23, 0x24, 0x01, 0x07, 0x24, 0x02,
0x05, 0x25, 0x03, 0x22, 0x1E, 0x2C, 0x04, 0x10,
0x30, 0x34, 0x41, 0x41, 0x30, 0x31, 0x41, 0x43,
0x32, 0x33, 0x31, 0x34, 0x30, 0x30, 0x4C, 0x50,
0x2C, 0x09, 0x06, 0x31, 0x2E, 0x34, 0x72, 0x63,
0x35, 0x24, 0x0C, 0x01, 0x18,
};
// clang-format on
static const uint32_t kIdentifyResponseLen = 53;
void CheckStrictAliasing(nlTestSuite * inSuite, void * inContext)
{
const uint32_t kProfile_Id = 0x0000000e;
CHIP_ERROR err = CHIP_NO_ERROR;
TLVReader reader;
reader.Init(sIdentifyResponseBuf, kIdentifyResponseLen);
reader.ImplicitProfileId = kProfile_Id;
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, reader.GetTag() == ProfileTag(kProfile_Id, 1));
}
/**
* Test CHIP TLV Writer Copy Container
*/
void TestCHIPTLVWriterCopyContainer(nlTestSuite * inSuite)
{
uint8_t buf[2048];
{
TLVWriter writer;
TLVReader reader;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
CHIP_ERROR err = writer.CopyContainer(reader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
uint32_t encodedLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
int memcmpRes = memcmp(buf, Encoding1, encodedLen);
NL_TEST_ASSERT(inSuite, memcmpRes == 0);
}
{
TLVWriter writer;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
CHIP_ERROR err = writer.CopyContainer(ProfileTag(TestProfile_1, 1), Encoding1, sizeof(Encoding1));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
uint32_t encodedLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
int memcmpRes = memcmp(buf, Encoding1, encodedLen);
NL_TEST_ASSERT(inSuite, memcmpRes == 0);
}
}
/**
* Test CHIP TLV Writer Copy Element
*/
void TestCHIPTLVWriterCopyElement(nlTestSuite * inSuite)
{
CHIP_ERROR err;
uint8_t expectedBuf[2048], testBuf[2048];
uint32_t expectedLen, testLen;
TLVWriter writer;
TLVType outerContainerType;
enum
{
kRepeatCount = 3
};
writer.Init(expectedBuf);
writer.ImplicitProfileId = TestProfile_2;
err = writer.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
for (int i = 0; i < kRepeatCount; i++)
{
WriteEncoding1(inSuite, writer);
}
err = writer.EndContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
expectedLen = writer.GetLengthWritten();
writer.Init(testBuf);
writer.ImplicitProfileId = TestProfile_2;
err = writer.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
for (int i = 0; i < kRepeatCount; i++)
{
TLVReader reader;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
err = writer.CopyElement(reader);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.EndContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
testLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, testLen == expectedLen);
int memcmpRes = memcmp(testBuf, expectedBuf, testLen);
NL_TEST_ASSERT(inSuite, memcmpRes == 0);
}
void PreserveSizeWrite(nlTestSuite * inSuite, TLVWriter & writer, bool preserveSize)
{
CHIP_ERROR err;
TLVWriter writer2;
// TLVTagControl::FullyQualified_8Bytes
err = writer.Put(ProfileTag(TestProfile_1, 4000000000ULL), static_cast<int64_t>(40000000000ULL), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(ProfileTag(TestProfile_1, 4000000000ULL), static_cast<int16_t>(12345), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Put(ProfileTag(TestProfile_1, 4000000000ULL), static_cast<float>(1.0));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
TLVWriter writer3;
err = writer2.OpenContainer(ContextTag(0), kTLVType_Array, writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<uint8_t>(42), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<uint16_t>(42), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<uint32_t>(42), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<uint64_t>(40000000000ULL), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int8_t>(-17), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int16_t>(-17), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int32_t>(-170000), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int64_t>(-170000), preserveSize);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// the below cases are for full coverage of PUTs
err = writer3.Put(AnonymousTag(), static_cast<uint64_t>(65535), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int64_t>(32767), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer3.Put(AnonymousTag(), static_cast<int64_t>(40000000000ULL), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.CloseContainer(writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
/**
* Test CHIP TLV Writer with Preserve Size
*/
void TestCHIPTLVWriterPreserveSize(nlTestSuite * inSuite)
{
uint8_t buf[2048];
TLVWriter writer;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
PreserveSizeWrite(inSuite, writer, true);
uint32_t encodedLen = writer.GetLengthWritten();
NL_TEST_ASSERT(inSuite, encodedLen == 105);
}
/**
* Test error handling of CHIP TLV Writer
*/
void TestCHIPTLVWriterErrorHandling(nlTestSuite * inSuite)
{
CHIP_ERROR err;
uint8_t buf[2048];
TLVWriter writer, writer2, writer3;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
// OpenContainer() for non-container
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Boolean, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// Since OpenContainer failed, writer2 remains uninitialized.
writer2.Init(nullptr, 0);
// CloseContainer() for non-container
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
// OpenContainer() failure
err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer3);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// CloseContainer() failure
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_CONTAINER_OPEN);
// StartContainer()
TLVType outerContainerType;
err = writer.StartContainer(ProfileTag(TestProfile_2, 4000000000ULL), kTLVType_Boolean, outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// EndContainer()
outerContainerType = kTLVType_Boolean;
err = writer.EndContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
// PutPreEncodedContainer()
TLVReader reader;
reader.Init(buf, 2048);
err = writer.PutPreEncodedContainer(ProfileTag(TestProfile_2, 4000000000ULL), kTLVType_Boolean, reader.GetReadPoint(),
reader.GetRemainingLength());
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INVALID_ARGUMENT);
}
void TestCHIPTLVEmptyString(nlTestSuite * inSuite)
{
uint8_t buf[2];
TLVWriter writer;
CHIP_ERROR err;
ByteSpan s;
writer.Init(buf);
err = writer.PutString(AnonymousTag(), nullptr, 0);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
TLVReader reader;
reader.Init(buf);
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.Get(s);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, s.data() == nullptr);
NL_TEST_ASSERT(inSuite, s.size() == 0);
}
/**
* Test CHIP TLV Writer
*/
void CheckCHIPTLVWriter(nlTestSuite * inSuite, void * inContext)
{
TestCHIPTLVWriterCopyContainer(inSuite);
TestCHIPTLVWriterCopyElement(inSuite);
TestCHIPTLVWriterPreserveSize(inSuite);
TestCHIPTLVWriterErrorHandling(inSuite);
TestCHIPTLVEmptyString(inSuite);
}
void SkipNonContainer(nlTestSuite * inSuite)
{
TLVReader reader;
const uint8_t * readpoint1 = nullptr;
const uint8_t * readpoint2 = nullptr;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
TestSkip(inSuite, reader);
readpoint1 = reader.GetReadPoint();
// Skip again, to check the operation is idempotent
TestSkip(inSuite, reader);
readpoint2 = reader.GetReadPoint();
NL_TEST_ASSERT(inSuite, readpoint1 == readpoint2);
}
void SkipContainer(nlTestSuite * inSuite)
{
TLVReader reader;
const uint8_t * readpoint1 = nullptr;
const uint8_t * readpoint2 = nullptr;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
TestSkip(inSuite, reader);
readpoint1 = reader.GetReadPoint();
// Skip again, to check the operation is idempotent
TestSkip(inSuite, reader);
readpoint2 = reader.GetReadPoint();
NL_TEST_ASSERT(inSuite, readpoint1 == readpoint2);
}
void NextContainer(nlTestSuite * inSuite)
{
TLVReader reader;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
CHIP_ERROR err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
}
/**
* Test CHIP TLV Reader Skip functions
*/
void TestCHIPTLVReaderSkip(nlTestSuite * inSuite)
{
SkipNonContainer(inSuite);
SkipContainer(inSuite);
NextContainer(inSuite);
}
/**
* Test CHIP TLV Reader Dup functions
*/
void TestCHIPTLVReaderDup(nlTestSuite * inSuite)
{
TLVReader reader;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
TestNext<TLVReader>(inSuite, reader);
{
TLVReader reader2;
TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
TestNext<TLVReader>(inSuite, reader2);
{
TLVReader reader3;
TestAndOpenContainer(inSuite, reader2, kTLVType_Array, ContextTag(0), reader3);
TestNext<TLVReader>(inSuite, reader3);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(42));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(42));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(42));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(42));
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint32_t>(42),
CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<uint64_t>(42),
CHIP_ERROR_WRONG_TLV_TYPE);
TestNext<TLVReader>(inSuite, reader3);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int8_t>(-17));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int16_t>(-17));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(-17));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(-17));
TestNext<TLVReader>(inSuite, reader3);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int32_t>(-170000));
TEST_GET_NOERROR(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag(), static_cast<int64_t>(-170000));
TestNext<TLVReader>(inSuite, reader3);
TEST_GET(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<int64_t>(40000000000ULL),
CHIP_ERROR_WRONG_TLV_TYPE);
TEST_GET_NOERROR(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag(), static_cast<uint64_t>(40000000000ULL));
TestNext<TLVReader>(inSuite, reader3);
{
TLVReader reader4;
TestAndOpenContainer(inSuite, reader3, kTLVType_Structure, AnonymousTag(), reader4);
TestEndAndCloseContainer(inSuite, reader3, reader4);
}
TestNext<TLVReader>(inSuite, reader3);
{
TLVReader reader5;
TestAndOpenContainer(inSuite, reader3, kTLVType_List, AnonymousTag(), reader5);
TestNext<TLVReader>(inSuite, reader5);
TestNull(inSuite, reader5, ProfileTag(TestProfile_1, 17));
TestNext<TLVReader>(inSuite, reader5);
TestNull(inSuite, reader5, ProfileTag(TestProfile_2, 900000));
TestNext<TLVReader>(inSuite, reader5);
TestNull(inSuite, reader5, AnonymousTag());
TestNext<TLVReader>(inSuite, reader5);
{
TLVType outerContainerType;
TestAndEnterContainer<TLVReader>(inSuite, reader5, kTLVType_Structure, ProfileTag(TestProfile_2, 4000000000ULL),
outerContainerType);
TestNext<TLVReader>(inSuite, reader5);
TestDupString(inSuite, reader5, CommonTag(70000), sLargeString);
TestEndAndExitContainer<TLVReader>(inSuite, reader5, outerContainerType);
}
TestEndAndCloseContainer(inSuite, reader3, reader5);
}
TestEndAndCloseContainer(inSuite, reader2, reader3);
}
TestNext<TLVReader>(inSuite, reader2);
TestDupBytes(inSuite, reader2, ProfileTag(TestProfile_1, 5), reinterpret_cast<const uint8_t *>("This is a test"), 14);
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), 17.9f);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535),
static_cast<double>(17.9f));
TestNext<TLVReader>(inSuite, reader2);
TEST_GET_NOERROR(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), 17.9);
TestEndAndCloseContainer(inSuite, reader, reader2);
}
TestEnd<TLVReader>(inSuite, reader);
}
/**
* Test error handling of CHIP TLV Reader
*/
void TestCHIPTLVReaderErrorHandling(nlTestSuite * inSuite)
{
CHIP_ERROR err;
uint8_t buf[2048] = { 0 };
TLVReader reader;
reader.Init(buf);
reader.ImplicitProfileId = TestProfile_2;
// Get(bool&)
bool val;
err = reader.Get(val);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// Get(float&)
float numF;
err = reader.Get(numF);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// Get(double&)
double numD;
err = reader.Get(numD);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// Get(uint64_t&)
uint64_t num;
err = reader.Get(num);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// GetBytes()
uint8_t bBuf[16];
err = reader.GetBytes(bBuf, sizeof(bBuf));
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// GetString()
char sBuf[16];
err = reader.GetString(sBuf, sizeof(sBuf));
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
// OpenContainer()
TLVReader reader2;
err = reader.OpenContainer(reader2);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
// CloseContainer()
err = reader.CloseContainer(reader2);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
// EnterContainer()
TLVType outerContainerType = kTLVType_Boolean;
err = reader.EnterContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
// DupString()
char * str = static_cast<char *>(chip::Platform::MemoryAlloc(16));
err = reader.DupString(str);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
chip::Platform::MemoryFree(str);
// GetDataPtr()
const uint8_t * data = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(16));
err = reader.GetDataPtr(data);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
chip::Platform::MemoryFree(const_cast<uint8_t *>(data));
}
/**
* Test that CHIP TLV reader returns an error when a read is requested that
* would truncate the output.
*/
void TestCHIPTLVReaderTruncatedReads(nlTestSuite * inSuite)
{
uint8_t buf[2048];
TLVWriter writer;
TLVReader reader;
CHIP_ERROR err;
float outF;
// Setup: Write some values into the buffer
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
err = writer.Put(AnonymousTag(), double{ 12.5 });
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Test reading values from the buffer
reader.Init(buf);
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_FloatingPointNumber, AnonymousTag(), 12.5);
err = reader.Get(outF);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
}
/**
* Test CHIP TLV Reader in a use case
*/
void TestCHIPTLVReaderInPractice(nlTestSuite * inSuite)
{
uint8_t buf[2048];
TLVWriter writer;
TLVReader reader;
writer.Init(buf);
writer.ImplicitProfileId = TestProfile_2;
PreserveSizeWrite(inSuite, writer, true);
reader.Init(buf);
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, ProfileTag(TestProfile_1, 4000000000ULL),
static_cast<int64_t>(40000000000ULL));
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_SignedInteger, ProfileTag(TestProfile_1, 4000000000ULL),
static_cast<int64_t>(12345));
TestNext<TLVReader>(inSuite, reader);
TEST_GET_NOERROR(inSuite, reader, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_1, 4000000000ULL),
static_cast<float>(1.0));
}
void TestCHIPTLVReader_NextOverContainer_ProcessElement(nlTestSuite * inSuite, TLVReader & reader, void * context)
{
CHIP_ERROR err, nextRes1, nextRes2;
TLVType outerContainerType;
// If the current element is a container...
if (TLVTypeIsContainer(reader.GetType()))
{
// Make two copies of the reader
TLVReader readerClone1 = reader;
TLVReader readerClone2 = reader;
// Manually advance one of the readers to the element immediately after the container (if any).
err = readerClone1.EnterContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ForEachElement(inSuite, readerClone1, nullptr, nullptr);
err = readerClone1.ExitContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
nextRes1 = readerClone1.Next();
NL_TEST_ASSERT(inSuite, nextRes1 == CHIP_NO_ERROR || nextRes1 == CHIP_END_OF_TLV);
// For the other reader, skip over the entire container using the Next() method.
nextRes2 = readerClone2.Next();
NL_TEST_ASSERT(inSuite, nextRes2 == CHIP_NO_ERROR || nextRes2 == CHIP_END_OF_TLV);
// Verify the two readers end up in the same state/position.
NL_TEST_ASSERT(inSuite, nextRes1 == nextRes2);
NL_TEST_ASSERT(inSuite, readerClone1.GetType() == readerClone2.GetType());
NL_TEST_ASSERT(inSuite, readerClone1.GetReadPoint() == readerClone2.GetReadPoint());
}
}
/**
* Test using CHIP TLV Reader Next() method to skip over containers.
*/
void TestCHIPTLVReader_NextOverContainer(nlTestSuite * inSuite)
{
TLVReader reader;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
ForEachElement(inSuite, reader, nullptr, TestCHIPTLVReader_NextOverContainer_ProcessElement);
}
void TestCHIPTLVReader_SkipOverContainer_ProcessElement(nlTestSuite * inSuite, TLVReader & reader, void * context)
{
CHIP_ERROR err;
TLVType outerContainerType;
// If the current element is a container...
if (TLVTypeIsContainer(reader.GetType()))
{
// Make two copies of the reader
TLVReader readerClone1 = reader;
TLVReader readerClone2 = reader;
// Manually advance one of the readers to immediately after the container.
err = readerClone1.EnterContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ForEachElement(inSuite, readerClone1, nullptr, nullptr);
err = readerClone1.ExitContainer(outerContainerType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// For the other reader, skip over the entire container using the Skip() method.
err = readerClone2.Skip();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Verify the two readers end up in the same state/position.
NL_TEST_ASSERT(inSuite, readerClone1.GetType() == readerClone2.GetType());
NL_TEST_ASSERT(inSuite, readerClone1.GetReadPoint() == readerClone2.GetReadPoint());
}
}
/**
* Test using CHIP TLV Reader Skip() method to skip over containers.
*/
void TestCHIPTLVReader_SkipOverContainer(nlTestSuite * inSuite)
{
TLVReader reader;
reader.Init(Encoding1);
reader.ImplicitProfileId = TestProfile_2;
ForEachElement(inSuite, reader, nullptr, TestCHIPTLVReader_SkipOverContainer_ProcessElement);
}
/**
* Test CHIP TLV Reader
*/
void CheckCHIPTLVReader(nlTestSuite * inSuite, void * inContext)
{
TestCHIPTLVReaderSkip(inSuite);
TestCHIPTLVReaderDup(inSuite);
TestCHIPTLVReaderErrorHandling(inSuite);
TestCHIPTLVReaderTruncatedReads(inSuite);
TestCHIPTLVReaderInPractice(inSuite);
TestCHIPTLVReader_NextOverContainer(inSuite);
TestCHIPTLVReader_SkipOverContainer(inSuite);
}
/**
* Test CHIP TLV Items
*/
static void TestItems(nlTestSuite * inSuite, void * inContext)
{
CHIP_ERROR err = CHIP_NO_ERROR;
uint8_t sBuffer[256];
TLVWriter writer;
writer.Init(sBuffer);
TLVWriter writer2;
err = writer.OpenContainer(AnonymousTag(), kTLVType_Array, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
err = writer2.PutBoolean(AnonymousTag(), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int8_t>(-1));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int16_t>(-2));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int32_t>(-3));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int64_t>(-4));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<float>(-5.5));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<double>(-3.14159265358979323846));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.OpenContainer(AnonymousTag(), kTLVType_Array, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
{
err = writer2.PutBoolean(AnonymousTag(), false);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int8_t>(1));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int16_t>(2));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int32_t>(3));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<int64_t>(4));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<uint8_t>(5));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<uint16_t>(6));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<uint32_t>(7));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<uint64_t>(8));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<float>(9.9));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.Put(AnonymousTag(), static_cast<double>(3.14159265358979323846));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
/**
* Test CHIP TLV Containers
*/
static void TestContainers(nlTestSuite * inSuite, void * inContext)
{
CHIP_ERROR err = CHIP_NO_ERROR;
TLVWriter writer;
uint8_t sBuffer[256];
writer.Init(sBuffer);
TLVWriter writer2;
err = writer.OpenContainer(AnonymousTag(), kTLVType_Array, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
TLVType type = writer2.GetContainerType();
NL_TEST_ASSERT(inSuite, type == kTLVType_Array);
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.OpenContainer(AnonymousTag(), kTLVType_Structure, writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
type = writer2.GetContainerType();
NL_TEST_ASSERT(inSuite, type == kTLVType_Structure);
err = writer.CloseContainer(writer2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
/**
* Test CHIP TLV Basics
*/
static void CheckCHIPTLVBasics(nlTestSuite * inSuite, void * inContext)
{
TestItems(inSuite, inContext);
TestContainers(inSuite, inContext);
}
/**
* Test CHIP TLV Updater
*/
static void CheckCHIPUpdater(nlTestSuite * inSuite, void * inContext)
{
WriteAppendReadTest0(inSuite);
WriteAppendReadTest1(inSuite);
WriteFindAppendReadTest(inSuite, false); // Find an element
WriteFindAppendReadTest(inSuite, true); // Find a container
AppendReadTest(inSuite);
WriteDeleteReadTest(inSuite);
}
/**
* Test TLV CloseContainer symbol reservations
*/
class OptimisticTLVWriter : public TLVWriter
{
public:
void Init(uint8_t * buf, size_t maxLen);
};
void OptimisticTLVWriter::Init(uint8_t * buf, size_t maxLen)
{
TLVWriter::Init(buf, maxLen);
SetCloseContainerReserved(false);
}
static void CheckCloseContainerReserve(nlTestSuite * inSuite, void * inContext)
{
// We are writing the structure looking like:
//
// [{TestProfile_1:2: true}]
//
// the above should consume 11 bytes in the TLV encoding. The
// chosen buffer is too small for that, this test verifies that we
// fail in the right places in the code. With the standard
// TLVWriter, we now make provisions to reserve the space for the
// CloseContainer tag in the OpenContainer call. As a result, we
// expect to error out when we attempt to write out the value for
// the TestProfile_1:2 tag. In contrast, the
// `OptimisticTLVWriter` implements the earlier TLVWriter behavior
// and fails out in the last CloseContainer call. The error
// caught there is different because we run up against the mMaxLen
// rather than mRemainingLen check.
uint8_t buf[10];
uint8_t buf1[7];
CHIP_ERROR err = CHIP_NO_ERROR;
TLVWriter writer1;
OptimisticTLVWriter writer2;
TLVWriter innerWriter1, innerWriter2;
TLVType container1, container2;
writer1.Init(buf);
err = writer1.OpenContainer(AnonymousTag(), kTLVType_Array, innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = innerWriter1.OpenContainer(AnonymousTag(), kTLVType_Structure, innerWriter2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = innerWriter2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
err = innerWriter1.CloseContainer(innerWriter2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.CloseContainer(innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
writer2.Init(buf, sizeof(buf));
err = writer2.OpenContainer(AnonymousTag(), kTLVType_Array, innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = innerWriter1.OpenContainer(AnonymousTag(), kTLVType_Structure, innerWriter2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = innerWriter2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = innerWriter1.CloseContainer(innerWriter2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.CloseContainer(innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
// test the same scheme works on the Start/End container
writer1.Init(buf);
err = writer1.StartContainer(AnonymousTag(), kTLVType_Array, container1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.StartContainer(AnonymousTag(), kTLVType_Structure, container2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
err = writer1.EndContainer(container2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer1.EndContainer(container1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
writer2.Init(buf, sizeof(buf));
err = writer2.StartContainer(AnonymousTag(), kTLVType_Array, container1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.StartContainer(AnonymousTag(), kTLVType_Structure, container2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.EndContainer(container2);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.EndContainer(container1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
// Test that the reservations work for the empty containers
writer1.Init(buf1);
err = writer1.OpenContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
err = writer1.CloseContainer(innerWriter1);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
writer2.Init(buf1, sizeof(buf1));
err = writer2.OpenContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.CloseContainer(innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
writer1.Init(buf1);
err = writer1.StartContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, container1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
err = writer1.EndContainer(container1);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
writer2.Init(buf1, sizeof(buf1));
err = writer2.StartContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, container1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer2.EndContainer(container1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
// Test that the reservations work if the writer has a maxLen of 0.
writer1.Init(buf1, 0);
err = writer1.OpenContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
err = writer1.StartContainer(AnonymousTag(), kTLVType_Array, container1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
// Test again all cases from 0 to the length of buf1
for (uint32_t maxLen = 0; maxLen <= sizeof(buf); maxLen++)
{
// Open/CloseContainer
writer1.Init(buf, maxLen);
err = writer1.OpenContainer(AnonymousTag(), kTLVType_Array, innerWriter1);
if (err == CHIP_NO_ERROR)
err = innerWriter1.OpenContainer(AnonymousTag(), kTLVType_Structure, innerWriter2);
if (err == CHIP_NO_ERROR)
err = innerWriter2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
if (err == CHIP_NO_ERROR)
err = innerWriter1.CloseContainer(innerWriter2);
if (err == CHIP_NO_ERROR)
err = writer1.CloseContainer(innerWriter1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
// Start/EndContainer
writer1.Init(buf, maxLen);
if (err == CHIP_NO_ERROR)
err = writer1.StartContainer(AnonymousTag(), kTLVType_Array, container1);
if (err == CHIP_NO_ERROR)
err = writer1.StartContainer(AnonymousTag(), kTLVType_Structure, container2);
if (err == CHIP_NO_ERROR)
err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
if (err == CHIP_NO_ERROR)
err = writer1.EndContainer(container2);
if (err == CHIP_NO_ERROR)
err = writer1.EndContainer(container1);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
}
}
static CHIP_ERROR ReadFuzzedEncoding1(nlTestSuite * inSuite, TLVReader & reader)
{
CHIP_ERROR err = CHIP_NO_ERROR;
#define FUZZ_CHECK_VAL(TYPE, VAL) \
do \
{ \
TYPE val; \
ReturnErrorOnFailure(reader.Get(val)); \
VerifyOrReturnError(val == (VAL), CHIP_ERROR_INVALID_ARGUMENT); \
} while (0)
#define FUZZ_CHECK_STRING(VAL) \
do \
{ \
char buf[sizeof(VAL)]; \
VerifyOrReturnError(reader.GetLength() == strlen(VAL), CHIP_ERROR_INVALID_ADDRESS); \
ReturnErrorOnFailure(reader.GetString(buf, sizeof(buf))); \
VerifyOrReturnError(strcmp(buf, (VAL)) == 0, CHIP_ERROR_INVALID_ADDRESS); \
} while (0)
ReturnErrorOnFailure(reader.Next(kTLVType_Structure, ProfileTag(TestProfile_1, 1)));
{
TLVType outerContainer1Type;
ReturnErrorOnFailure(reader.EnterContainer(outerContainer1Type));
ReturnErrorOnFailure(reader.Next(kTLVType_Boolean, ProfileTag(TestProfile_1, 2)));
FUZZ_CHECK_VAL(bool, true);
ReturnErrorOnFailure(reader.Next(kTLVType_Boolean, ProfileTag(TestProfile_2, 2)));
FUZZ_CHECK_VAL(bool, false);
ReturnErrorOnFailure(reader.Next(kTLVType_Array, ContextTag(0)));
{
TLVType outerContainer2Type;
ReturnErrorOnFailure(reader.EnterContainer(outerContainer2Type));
ReturnErrorOnFailure(reader.Next(kTLVType_SignedInteger, AnonymousTag()));
FUZZ_CHECK_VAL(int8_t, 42);
FUZZ_CHECK_VAL(int16_t, 42);
FUZZ_CHECK_VAL(int32_t, 42);
FUZZ_CHECK_VAL(int64_t, 42);
FUZZ_CHECK_VAL(uint8_t, 42);
FUZZ_CHECK_VAL(uint16_t, 42);
FUZZ_CHECK_VAL(uint32_t, 42);
FUZZ_CHECK_VAL(uint64_t, 42);
ReturnErrorOnFailure(reader.Next(kTLVType_SignedInteger, AnonymousTag()));
FUZZ_CHECK_VAL(int8_t, -17);
FUZZ_CHECK_VAL(int16_t, -17);
FUZZ_CHECK_VAL(int32_t, -17);
FUZZ_CHECK_VAL(int64_t, -17);
ReturnErrorOnFailure(reader.Next(kTLVType_SignedInteger, AnonymousTag()));
FUZZ_CHECK_VAL(int32_t, -170000);
FUZZ_CHECK_VAL(int64_t, -170000);
ReturnErrorOnFailure(reader.Next(kTLVType_UnsignedInteger, AnonymousTag()));
FUZZ_CHECK_VAL(int64_t, 40000000000ULL);
FUZZ_CHECK_VAL(uint64_t, 40000000000ULL);
ReturnErrorOnFailure(reader.Next(kTLVType_Structure, AnonymousTag()));
{
TLVType outerContainer3Type;
ReturnErrorOnFailure(reader.EnterContainer(outerContainer3Type));
ReturnErrorOnFailure(reader.ExitContainer(outerContainer3Type));
}
ReturnErrorOnFailure(reader.Next(kTLVType_List, AnonymousTag()));
{
TLVType outerContainer3Type;
ReturnErrorOnFailure(reader.EnterContainer(outerContainer3Type));
ReturnErrorOnFailure(reader.Next(kTLVType_Null, ProfileTag(TestProfile_1, 17)));
ReturnErrorOnFailure(reader.Next(kTLVType_Null, ProfileTag(TestProfile_2, 900000)));
ReturnErrorOnFailure(reader.Next(kTLVType_Null, AnonymousTag()));
ReturnErrorOnFailure(reader.Next(kTLVType_Structure, ProfileTag(TestProfile_2, 4000000000ULL)));
{
TLVType outerContainer4Type;
ReturnErrorOnFailure(reader.EnterContainer(outerContainer4Type));
ReturnErrorOnFailure(reader.Next(kTLVType_UTF8String, CommonTag(70000)));
FUZZ_CHECK_STRING(sLargeString);
ReturnErrorOnFailure(reader.ExitContainer(outerContainer4Type));
}
ReturnErrorOnFailure(reader.ExitContainer(outerContainer3Type));
}
ReturnErrorOnFailure(reader.ExitContainer(outerContainer2Type));
}
ReturnErrorOnFailure(reader.Next(kTLVType_UTF8String, ProfileTag(TestProfile_1, 5)));
FUZZ_CHECK_STRING("This is a test");
ReturnErrorOnFailure(reader.Next(kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535)));
FUZZ_CHECK_VAL(double, (float) 17.9);
ReturnErrorOnFailure(reader.Next(kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536)));
FUZZ_CHECK_VAL(double, (double) 17.9);
ReturnErrorOnFailure(reader.ExitContainer(outerContainer1Type));
}
err = reader.Next();
if (err == CHIP_END_OF_TLV)
err = CHIP_NO_ERROR;
return CHIP_NO_ERROR;
}
static uint64_t sFuzzTestDurationMillis = 5000;
static uint8_t sFixedFuzzMask = 0;
static void TLVReaderFuzzTest(nlTestSuite * inSuite, void * inContext)
{
uint64_t now, endTime;
uint8_t fuzzedData[sizeof(Encoding1)];
// clang-format off
static uint8_t sFixedFuzzVals[] =
{
0x00,
0x01,
0xFF,
0x20, // 1-byte signed integer with context tag
0x21, // 2-byte signed integer with context tag
0x22, // 4-byte signed integer with context tag
0x23, // 8-byte signed integer with context tag
0x24, // 1-byte unsigned integer with context tag
0x25, // 1-byte unsigned integer with context tag
0x26, // 1-byte unsigned integer with context tag
0x27, // 1-byte unsigned integer with context tag
0x28, // Boolean false with context tag
0x29, // Boolean true with context tag
0x27, // UTF-8 string with 1-byte length and context tag
0x30, // Byte string with 1-byte length and context tag
0x35, // Structure with context tag
0x36, // Array with context tag
0x18, // End of container
};
// clang-format on
memcpy(fuzzedData, Encoding1, sizeof(fuzzedData));
now = chip::test_utils::TimeMonotonicMillis();
endTime = now + sFuzzTestDurationMillis + 1;
srand(static_cast<unsigned int>(now));
size_t m = 0;
while (true)
{
for (size_t i = 0; i < sizeof(fuzzedData); i++)
{
uint8_t origVal = fuzzedData[i];
if (m < sizeof(sFixedFuzzVals))
{
if (origVal == sFixedFuzzVals[m])
continue;
fuzzedData[i] = sFixedFuzzVals[m];
}
else
{
uint8_t fuzzMask = sFixedFuzzMask;
while (fuzzMask == 0)
fuzzMask = static_cast<uint8_t>(rand() & 0xFF);
fuzzedData[i] ^= fuzzMask;
}
TLVReader reader;
reader.Init(fuzzedData);
reader.ImplicitProfileId = TestProfile_2;
CHIP_ERROR readRes = ReadFuzzedEncoding1(inSuite, reader);
NL_TEST_ASSERT(inSuite, readRes != CHIP_NO_ERROR);
if (readRes == CHIP_NO_ERROR)
{
printf("Unexpected success of fuzz test: offset %u, original value 0x%02X, mutated value 0x%02X\n",
static_cast<unsigned>(i), static_cast<unsigned>(origVal), static_cast<unsigned>(fuzzedData[i]));
return;
}
now = chip::test_utils::TimeMonotonicMillis();
if (now >= endTime)
return;
fuzzedData[i] = origVal;
}
if (m < sizeof(sFixedFuzzVals))
m++;
}
}
static void AssertCanReadString(nlTestSuite * inSuite, ContiguousBufferTLVReader & reader, const char * expectedString)
{
Span<const char> str;
CHIP_ERROR err = reader.GetStringView(str);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, str.size() == strlen(expectedString));
NL_TEST_ASSERT(inSuite, strncmp(str.data(), expectedString, str.size()) == 0);
}
static void AssertCannotReadString(nlTestSuite * inSuite, ContiguousBufferTLVReader & reader)
{
Span<const char> str;
CHIP_ERROR err = reader.GetStringView(str);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
}
static void CheckGetStringView(nlTestSuite * inSuite, void * inContext)
{
uint8_t buf[256];
const char testString[] = "This is a test";
{
TLVWriter writer;
writer.Init(buf);
CHIP_ERROR err = writer.PutString(CommonTag(0), testString);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// First check that basic read from entire buffer works.
ContiguousBufferTLVReader reader;
reader.Init(buf);
reader.Next();
AssertCanReadString(inSuite, reader, testString);
// Now check that read from a buffer bounded by the number of bytes
// written works.
reader.Init(buf, writer.GetLengthWritten());
reader.Next();
AssertCanReadString(inSuite, reader, testString);
// Now check that read from a buffer bounded by fewer than the number of
// bytes written fails.
reader.Init(buf, writer.GetLengthWritten() - 1);
reader.Next();
AssertCannotReadString(inSuite, reader);
}
{
// Check that an integer cannot be read as a string.
TLVWriter writer;
writer.Init(buf);
CHIP_ERROR err = writer.Put(CommonTag(0), static_cast<uint8_t>(5));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ContiguousBufferTLVReader reader;
reader.Init(buf);
reader.Next();
AssertCannotReadString(inSuite, reader);
}
{
// Check that an octet string cannot be read as a string.
TLVWriter writer;
writer.Init(buf);
CHIP_ERROR err =
writer.PutBytes(CommonTag(0), reinterpret_cast<const uint8_t *>(testString), static_cast<uint32_t>(strlen(testString)));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ContiguousBufferTLVReader reader;
reader.Init(buf);
reader.Next();
AssertCannotReadString(inSuite, reader);
}
{
// Check that a manually constructed string can be read as a string.
const uint8_t shortString[] = { CHIP_TLV_UTF8_STRING_2ByteLength(CHIP_TLV_TAG_COMMON_PROFILE_2Bytes(0), 2, 'a', 'b') };
ContiguousBufferTLVReader reader;
reader.Init(shortString);
reader.Next();
AssertCanReadString(inSuite, reader, "ab");
}
{
// Check that a manually constructed string with bogus length cannot be read as a string.
const uint8_t shortString[] = { CHIP_TLV_UTF8_STRING_2ByteLength(CHIP_TLV_TAG_COMMON_PROFILE_2Bytes(0), 3, 'a', 'b') };
ContiguousBufferTLVReader reader;
reader.Init(shortString);
reader.Next();
AssertCannotReadString(inSuite, reader);
}
}
static void AssertCanReadBytes(nlTestSuite * inSuite, ContiguousBufferTLVReader & reader, const ByteSpan & expectedBytes)
{
ByteSpan bytes;
CHIP_ERROR err = reader.GetByteView(bytes);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, bytes.data_equal(expectedBytes));
}
static void AssertCannotReadBytes(nlTestSuite * inSuite, ContiguousBufferTLVReader & reader)
{
ByteSpan bytes;
CHIP_ERROR err = reader.GetByteView(bytes);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
}
static void CheckGetByteView(nlTestSuite * inSuite, void * inContext)
{
uint8_t buf[256];
const uint8_t testBytes[] = { 'T', 'h', 'i', 's', 'i', 's', 'a', 't', 'e', 's', 't', '\0' };
{
TLVWriter writer;
writer.Init(buf);
CHIP_ERROR err = writer.PutBytes(CommonTag(0), testBytes, sizeof(testBytes));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// First check that basic read from entire buffer works.
ContiguousBufferTLVReader reader;
reader.Init(buf);
reader.Next();
AssertCanReadBytes(inSuite, reader, ByteSpan(testBytes));
// Now check that read from a buffer bounded by the number of bytes
// written works.
reader.Init(buf, writer.GetLengthWritten());
reader.Next();
AssertCanReadBytes(inSuite, reader, ByteSpan(testBytes));
// Now check that read from a buffer bounded by fewer than the number of
// bytes written fails.
reader.Init(buf, writer.GetLengthWritten() - 1);
reader.Next();
AssertCannotReadBytes(inSuite, reader);
}
{
// Check that an integer cannot be read as an octet string.
TLVWriter writer;
writer.Init(buf);
CHIP_ERROR err = writer.Put(CommonTag(0), static_cast<uint8_t>(5));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ContiguousBufferTLVReader reader;
reader.Init(buf);
reader.Next();
AssertCannotReadBytes(inSuite, reader);
}
{
// Check that an string cannot be read as an octet string.
TLVWriter writer;
writer.Init(buf);
CHIP_ERROR err = writer.PutString(CommonTag(0), reinterpret_cast<const char *>(testBytes));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ContiguousBufferTLVReader reader;
reader.Init(buf);
reader.Next();
AssertCannotReadBytes(inSuite, reader);
}
{
// Check that a manually constructed octet string can be read as octet string.
const uint8_t shortBytes[] = { CHIP_TLV_BYTE_STRING_2ByteLength(CHIP_TLV_TAG_COMMON_PROFILE_2Bytes(0), 2, 1, 2) };
ContiguousBufferTLVReader reader;
reader.Init(shortBytes);
reader.Next();
const uint8_t expectedBytes[] = { 1, 2 };
AssertCanReadBytes(inSuite, reader, ByteSpan(expectedBytes));
}
{
// Check that a manually constructed octet string with bogus length
// cannot be read as an octet string.
const uint8_t shortBytes[] = { CHIP_TLV_BYTE_STRING_2ByteLength(CHIP_TLV_TAG_COMMON_PROFILE_2Bytes(0), 3, 1, 2) };
ContiguousBufferTLVReader reader;
reader.Init(shortBytes);
reader.Next();
AssertCannotReadBytes(inSuite, reader);
}
}
static void CheckCHIPTLVScopedBuffer(nlTestSuite * inSuite, void * inContext)
{
Platform::ScopedMemoryBuffer<uint8_t> buf;
CHIP_ERROR err;
buf.Calloc(64);
NL_TEST_ASSERT(inSuite, buf.Get() != nullptr);
{
ScopedBufferTLVWriter writer(std::move(buf), 64);
NL_TEST_ASSERT(inSuite, buf.Get() == nullptr); // // NOLINT(bugprone-use-after-move)
err = writer.Put(TLV::AnonymousTag(), (uint8_t) 33);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = writer.Finalize(buf);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, buf.Get() != nullptr);
err = writer.Put(TLV::AnonymousTag(), (uint8_t) 33);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
}
{
ScopedBufferTLVReader reader;
uint8_t val;
reader.Init(std::move(buf), 64);
err = reader.Next();
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = reader.Get(val);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, val == 33);
reader.TakeBuffer(buf);
NL_TEST_ASSERT(inSuite, buf.Get() != nullptr);
err = reader.Get(val);
NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
}
}
// Test Suite
/**
* Test Suite that lists all the test functions.
*/
// clang-format off
static const nlTest sTests[] =
{
NL_TEST_DEF("Simple Write Read Test", CheckSimpleWriteRead),
NL_TEST_DEF("Inet Buffer Test", CheckPacketBuffer),
NL_TEST_DEF("Buffer Overflow Test", CheckBufferOverflow),
NL_TEST_DEF("Pretty Print Test", CheckPrettyPrinter),
NL_TEST_DEF("Pretty Octet String Print Test", CheckOctetStringPrettyPrinter),
NL_TEST_DEF("Data Macro Test", CheckDataMacro),
NL_TEST_DEF("Strict Aliasing Test", CheckStrictAliasing),
NL_TEST_DEF("CHIP TLV Basics", CheckCHIPTLVBasics),
NL_TEST_DEF("CHIP TLV Writer", CheckCHIPTLVWriter),
NL_TEST_DEF("CHIP TLV Reader", CheckCHIPTLVReader),
NL_TEST_DEF("CHIP TLV Utilities", CheckCHIPTLVUtilities),
NL_TEST_DEF("CHIP TLV Updater", CheckCHIPUpdater),
NL_TEST_DEF("CHIP TLV Empty Find", CheckCHIPTLVEmptyFind),
NL_TEST_DEF("CHIP Circular TLV buffer, simple", CheckCircularTLVBufferSimple),
NL_TEST_DEF("CHIP Circular TLV buffer, mid-buffer start", CheckCircularTLVBufferStartMidway),
NL_TEST_DEF("CHIP Circular TLV buffer, straddle", CheckCircularTLVBufferEvictStraddlingEvent),
NL_TEST_DEF("CHIP Circular TLV buffer, edge", CheckCircularTLVBufferEdge),
NL_TEST_DEF("CHIP TLV Printf", CheckCHIPTLVPutStringF),
NL_TEST_DEF("CHIP TLV String Span", CheckCHIPTLVPutStringSpan),
NL_TEST_DEF("CHIP TLV Printf, Circular TLV buf", CheckCHIPTLVPutStringFCircular),
NL_TEST_DEF("CHIP TLV Skip non-contiguous", CheckCHIPTLVSkipCircular),
NL_TEST_DEF("CHIP TLV ByteSpan", CheckCHIPTLVByteSpan),
NL_TEST_DEF("CHIP TLV Scoped Buffer", CheckCHIPTLVScopedBuffer),
NL_TEST_DEF("CHIP TLV Check reserve", CheckCloseContainerReserve),
NL_TEST_DEF("CHIP TLV Reader Fuzz Test", TLVReaderFuzzTest),
NL_TEST_DEF("CHIP TLV GetStringView Test", CheckGetStringView),
NL_TEST_DEF("CHIP TLV GetByteView Test", CheckGetByteView),
NL_TEST_DEF("Int Min/Max Test", TestIntMinMax),
NL_TEST_SENTINEL()
};
// clang-format on
/**
* Set up the test suite.
*/
int TestCHIPTLV_Setup(void * inContext)
{
CHIP_ERROR error = chip::Platform::MemoryInit();
if (error != CHIP_NO_ERROR)
return FAILURE;
return SUCCESS;
}
/**
* Tear down the test suite.
*/
int TestCHIPTLV_Teardown(void * inContext)
{
chip::Platform::MemoryShutdown();
return SUCCESS;
}
int TestCHIPTLV(void)
{
// clang-format off
nlTestSuite theSuite =
{
"chip-tlv",
&sTests[0],
TestCHIPTLV_Setup,
TestCHIPTLV_Teardown
};
// clang-format on
return chip::ExecuteTestsWithContext<TestTLVContext>(&theSuite, &theSuite);
}
CHIP_REGISTER_TEST_SUITE(TestCHIPTLV)