| /* |
| * |
| * Copyright (c) 2020-2023 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/CHIPCore.h> |
| #include <lib/core/TLV.h> |
| #include <lib/core/TLVCircularBuffer.h> |
| #include <lib/core/TLVData.h> |
| #include <lib/core/TLVDebug.h> |
| #include <lib/core/TLVUtilities.h> |
| |
| #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 CheckTLVUtilities(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 CheckTLVEmptyFind(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(TLVCircularBuffer & 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); |
| TLVCircularBuffer 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); |
| TLVCircularBuffer 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; |
| TLVCircularBuffer 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; |
| |
| TLVCircularBuffer buffer(backingStore, sizeof(backingStore)); |
| TLVCircularBuffer 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 CheckTLVPutStringF(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 CheckTLVPutStringSpan(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 CheckTLVPutStringFCircular(nlTestSuite * inSuite, void * inContext) |
| { |
| const size_t bufsize = 40; |
| char strBuffer[bufsize]; |
| char valStr[bufsize]; |
| uint8_t backingStore[bufsize]; |
| CircularTLVWriter writer; |
| CircularTLVReader reader; |
| TLVCircularBuffer 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 CheckTLVByteSpan(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); |
| } |
| |
| #define IS1_CHAR "\x1F" |
| |
| void CheckTLVCharSpan(nlTestSuite * inSuite, void * inContext) |
| { |
| struct CharSpanTestCase |
| { |
| const char * testString; |
| const char * expectedString; |
| }; |
| |
| // clang-format off |
| static CharSpanTestCase sCharSpanTestCases[] = { |
| // Test String Expected String from Get() |
| // ================================================================================================== |
| { "This is a test case #0", "This is a test case #0" }, |
| { "This is a test case #1" IS1_CHAR "Test Localized String Identifier", "This is a test case #1" }, |
| { "This is a test case #2 " IS1_CHAR "abc" IS1_CHAR "def", "This is a test case #2 " }, |
| { "This is a test case #3" IS1_CHAR, "This is a test case #3" }, |
| { "Thé" IS1_CHAR, "Thé" }, |
| { IS1_CHAR " abc " IS1_CHAR " def", "" }, |
| }; |
| // clang-format on |
| |
| for (auto & testCase : sCharSpanTestCases) |
| { |
| uint8_t backingStore[100]; |
| TLVWriter writer; |
| TLVReader reader; |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| writer.Init(backingStore); |
| |
| err = writer.PutString(ProfileTag(TestProfile_1, 1), testCase.testString); |
| 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::CharSpan readerSpan; |
| err = reader.Get(readerSpan); |
| NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, strlen(testCase.expectedString) == readerSpan.size()); |
| NL_TEST_ASSERT(inSuite, memcmp(readerSpan.data(), testCase.expectedString, strlen(testCase.expectedString)) == 0); |
| } |
| } |
| |
| void CheckTLVGetLocalizedStringIdentifier(nlTestSuite * inSuite, void * inContext) |
| { |
| struct CharSpanTestCase |
| { |
| const char * testString; |
| Optional<LocalizedStringIdentifier> expectedLSID; |
| CHIP_ERROR expectedResult; |
| }; |
| |
| // clang-format off |
| static CharSpanTestCase sCharSpanTestCases[] = { |
| // Test String Expected LocalizedStringIdentifier from Get() Expected Return |
| // ============================================================================================================================================= |
| { "This is a test case #0", chip::Optional<LocalizedStringIdentifier>(), CHIP_NO_ERROR }, |
| { "This is a test case #1" IS1_CHAR "0123", chip::Optional<LocalizedStringIdentifier>(), CHIP_ERROR_INVALID_TLV_ELEMENT }, |
| { "This is a test case #2" IS1_CHAR "123" IS1_CHAR "3210", chip::Optional<LocalizedStringIdentifier>(0x123), CHIP_NO_ERROR }, |
| { "This is a test case #3" IS1_CHAR "012", chip::Optional<LocalizedStringIdentifier>(), CHIP_ERROR_INVALID_TLV_ELEMENT }, |
| { "This is a test case #3" IS1_CHAR "12", chip::Optional<LocalizedStringIdentifier>(0x12), CHIP_NO_ERROR }, |
| { "Thé" IS1_CHAR "", chip::Optional<LocalizedStringIdentifier>(), CHIP_NO_ERROR }, |
| { "Thé" IS1_CHAR "7", chip::Optional<LocalizedStringIdentifier>(0x7), CHIP_NO_ERROR }, |
| { "Thé" IS1_CHAR "1FA", chip::Optional<LocalizedStringIdentifier>(0x1FA), CHIP_NO_ERROR }, |
| { "" IS1_CHAR "1FA", chip::Optional<LocalizedStringIdentifier>(0x1FA), CHIP_NO_ERROR }, |
| { "Thé" IS1_CHAR "1FAB", chip::Optional<LocalizedStringIdentifier>(0x1FAB), CHIP_NO_ERROR }, |
| { "Thé" IS1_CHAR "1FAb", chip::Optional<LocalizedStringIdentifier>(), CHIP_ERROR_INVALID_TLV_ELEMENT }, |
| { "Thé" IS1_CHAR "1FABC", chip::Optional<LocalizedStringIdentifier>(), CHIP_ERROR_INVALID_TLV_ELEMENT }, |
| { "Thé" IS1_CHAR "1FA" IS1_CHAR "", chip::Optional<LocalizedStringIdentifier>(0x1FA), CHIP_NO_ERROR }, |
| { "Thé" IS1_CHAR "1FA" IS1_CHAR "F8sa===", chip::Optional<LocalizedStringIdentifier>(0x1FA), CHIP_NO_ERROR }, |
| }; |
| // clang-format on |
| |
| for (auto & testCase : sCharSpanTestCases) |
| { |
| uint8_t backingStore[100]; |
| TLVWriter writer; |
| TLVReader reader; |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| writer.Init(backingStore); |
| |
| err = writer.PutString(ProfileTag(TestProfile_1, 1), testCase.testString); |
| 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); |
| |
| Optional<LocalizedStringIdentifier> readerLSID; |
| err = reader.Get(readerLSID); |
| NL_TEST_ASSERT(inSuite, testCase.expectedResult == err); |
| NL_TEST_ASSERT(inSuite, testCase.expectedLSID == readerLSID); |
| } |
| |
| // Error case: A case of TLVReader buffer underrun. |
| // Expected error after Next() call is: CHIP_ERROR_TLV_UNDERRUN |
| { |
| uint8_t backingStore[100]; |
| TLVWriter writer; |
| TLVReader reader; |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| writer.Init(backingStore); |
| |
| err = writer.PutString(ProfileTag(TestProfile_1, 1), sCharSpanTestCases[2].testString); |
| NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| |
| err = writer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| |
| reader.Init(backingStore, writer.GetLengthWritten() - 1); |
| err = reader.Next(); |
| NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_UNDERRUN); |
| } |
| |
| // Error case: the reader is on a bytestring, not utf-8 string. |
| // Expected error after Get(Optional<LocalizedStringIdentifier> &) call is: CHIP_ERROR_WRONG_TLV_TYPE |
| { |
| uint8_t backingStore[100]; |
| TLVWriter writer; |
| TLVReader reader; |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| writer.Init(backingStore); |
| |
| err = writer.PutBytes(ProfileTag(TestProfile_1, 1), reinterpret_cast<const uint8_t *>(sCharSpanTestCases[2].testString), |
| static_cast<uint32_t>(strlen(sCharSpanTestCases[2].testString))); |
| 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); |
| |
| Optional<LocalizedStringIdentifier> readerLSID; |
| err = reader.Get(readerLSID); |
| NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE); |
| NL_TEST_ASSERT(inSuite, readerLSID == Optional<LocalizedStringIdentifier>()); |
| } |
| } |
| |
| void CheckTLVSkipCircular(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; |
| TLVCircularBuffer 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 TestTLVWriterCopyContainer(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 TestTLVWriterCopyElement(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 TestTLVWriterPreserveSize(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 TestTLVWriterErrorHandling(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 TestTLVEmptyString(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 CheckTLVWriter(nlTestSuite * inSuite, void * inContext) |
| { |
| TestTLVWriterCopyContainer(inSuite); |
| |
| TestTLVWriterCopyElement(inSuite); |
| |
| TestTLVWriterPreserveSize(inSuite); |
| |
| TestTLVWriterErrorHandling(inSuite); |
| |
| TestTLVEmptyString(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 TestTLVReaderSkip(nlTestSuite * inSuite) |
| { |
| SkipNonContainer(inSuite); |
| |
| SkipContainer(inSuite); |
| |
| NextContainer(inSuite); |
| } |
| |
| /** |
| * Test CHIP TLV Reader Dup functions |
| */ |
| void TestTLVReaderDup(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 TestTLVReaderErrorHandling(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 TestTLVReaderTruncatedReads(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 TestTLVReaderInPractice(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 TestTLVReader_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 TestTLVReader_NextOverContainer(nlTestSuite * inSuite) |
| { |
| TLVReader reader; |
| |
| reader.Init(Encoding1); |
| reader.ImplicitProfileId = TestProfile_2; |
| |
| ForEachElement(inSuite, reader, nullptr, TestTLVReader_NextOverContainer_ProcessElement); |
| } |
| |
| void TestTLVReader_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 TestTLVReader_SkipOverContainer(nlTestSuite * inSuite) |
| { |
| TLVReader reader; |
| |
| reader.Init(Encoding1); |
| reader.ImplicitProfileId = TestProfile_2; |
| |
| ForEachElement(inSuite, reader, nullptr, TestTLVReader_SkipOverContainer_ProcessElement); |
| } |
| |
| /** |
| * Test CHIP TLV Reader |
| */ |
| void CheckTLVReader(nlTestSuite * inSuite, void * inContext) |
| { |
| TestTLVReaderSkip(inSuite); |
| |
| TestTLVReaderDup(inSuite); |
| |
| TestTLVReaderErrorHandling(inSuite); |
| |
| TestTLVReaderTruncatedReads(inSuite); |
| |
| TestTLVReaderInPractice(inSuite); |
| |
| TestTLVReader_NextOverContainer(inSuite); |
| |
| TestTLVReader_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 CheckTLVBasics(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 CheckTLVScopedBuffer(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", CheckTLVBasics), |
| NL_TEST_DEF("CHIP TLV Writer", CheckTLVWriter), |
| NL_TEST_DEF("CHIP TLV Reader", CheckTLVReader), |
| NL_TEST_DEF("CHIP TLV Utilities", CheckTLVUtilities), |
| NL_TEST_DEF("CHIP TLV Updater", CheckCHIPUpdater), |
| NL_TEST_DEF("CHIP TLV Empty Find", CheckTLVEmptyFind), |
| 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", CheckTLVPutStringF), |
| NL_TEST_DEF("CHIP TLV String Span", CheckTLVPutStringSpan), |
| NL_TEST_DEF("CHIP TLV Printf, Circular TLV buf", CheckTLVPutStringFCircular), |
| NL_TEST_DEF("CHIP TLV Skip non-contiguous", CheckTLVSkipCircular), |
| NL_TEST_DEF("CHIP TLV ByteSpan", CheckTLVByteSpan), |
| NL_TEST_DEF("CHIP TLV CharSpan", CheckTLVCharSpan), |
| NL_TEST_DEF("CHIP TLV Get LocalizedStringIdentifier", CheckTLVGetLocalizedStringIdentifier), |
| NL_TEST_DEF("CHIP TLV Scoped Buffer", CheckTLVScopedBuffer), |
| 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 TestTLV_Setup(void * inContext) |
| { |
| CHIP_ERROR error = chip::Platform::MemoryInit(); |
| if (error != CHIP_NO_ERROR) |
| return FAILURE; |
| return SUCCESS; |
| } |
| |
| /** |
| * Tear down the test suite. |
| */ |
| int TestTLV_Teardown(void * inContext) |
| { |
| chip::Platform::MemoryShutdown(); |
| return SUCCESS; |
| } |
| |
| int TestTLV() |
| { |
| // clang-format off |
| nlTestSuite theSuite = |
| { |
| "chip-tlv", |
| &sTests[0], |
| TestTLV_Setup, |
| TestTLV_Teardown |
| }; |
| // clang-format on |
| |
| return chip::ExecuteTestsWithContext<TestTLVContext>(&theSuite, &theSuite); |
| } |
| |
| CHIP_REGISTER_TEST_SUITE(TestTLV) |