blob: 2ac64670d3d596ae4c79845c6d0874fb3f7cd033 [file] [log] [blame]
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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.
*/
#include <stdio.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app/data-model/Decode.h>
#include <app/data-model/Encode.h>
#include <lib/support/UnitTestRegistration.h>
#include <lib/support/jsontlv/JsonToTlv.h>
#include <lib/support/jsontlv/TextFormat.h>
#include <lib/support/jsontlv/TlvToJson.h>
#include <nlunit-test.h>
#include <string>
namespace {
using namespace chip::Encoding;
using namespace chip;
using namespace chip::app;
constexpr uint32_t kImplicitProfileId = 0x1122;
nlTestSuite * gSuite;
void PrintSpan(const char * prefix, const ByteSpan & span)
{
printf("%s", prefix);
for (size_t i = 0; i < span.size(); i++)
{
printf("%02X ", span.data()[i]);
}
printf("\n");
}
void CheckValidConversion(const std::string & jsonOriginal, const ByteSpan & tlvEncoding, const std::string & jsonExpected)
{
CHIP_ERROR err = CHIP_NO_ERROR;
bool match = false;
uint8_t buf[256];
MutableByteSpan tlvEncodingLocal(buf);
err = JsonToTlv(jsonOriginal, tlvEncodingLocal);
NL_TEST_ASSERT(gSuite, err == CHIP_NO_ERROR);
match = tlvEncodingLocal.data_equal(tlvEncoding);
NL_TEST_ASSERT(gSuite, match);
if (!match)
{
printf("ERROR: TLV Encoding Doesn't Match!\n");
PrintSpan("TLV Encoding Provided as Input for Reference: ", tlvEncoding);
PrintSpan("TLV Encoding Generated from Json Input String: ", tlvEncodingLocal);
}
std::string generatedJsonString;
err = TlvToJson(tlvEncoding, generatedJsonString);
NL_TEST_ASSERT(gSuite, err == CHIP_NO_ERROR);
auto compactExpectedString = PrettyPrintJsonString(jsonExpected);
auto compactGeneratedString = PrettyPrintJsonString(generatedJsonString);
match = (compactGeneratedString == compactExpectedString);
NL_TEST_ASSERT(gSuite, match);
if (!match)
{
printf("ERROR: Json String Doesn't Match!\n");
printf("Expected Json String:\n%s\n", compactExpectedString.c_str());
printf("Generated Json String:\n%s\n", compactGeneratedString.c_str());
}
// Verify that Expected Json String Converts to the Same TLV Encoding
tlvEncodingLocal = MutableByteSpan(buf);
err = JsonToTlv(jsonOriginal, tlvEncodingLocal);
NL_TEST_ASSERT(gSuite, err == CHIP_NO_ERROR);
match = tlvEncodingLocal.data_equal(tlvEncoding);
NL_TEST_ASSERT(gSuite, match);
if (!match)
{
printf("ERROR: TLV Encoding Doesn't Match!\n");
PrintSpan("TLV Encoding Provided as Input for Reference: ", tlvEncoding);
PrintSpan("TLV Encoding Generated from Json Expected String: ", tlvEncodingLocal);
}
}
// Boolean true
void TestConverter_Boolean_True(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:BOOL\" : true\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Signed Integer 42, 1-octet
void TestConverter_SignedInt_1BytePositive(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<int8_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"2:INT\" : 42\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Signed Integer -17, 1-octet
void TestConverter_SignedInt_1ByteNegative(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(3), static_cast<int8_t>(-17)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"3:INT\" : -17\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Unsigned Integer 42, 1-octet
void TestConverter_UnsignedInt_1Byte(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(4), static_cast<uint8_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"value:4:UINT\" : 42\n"
"}\n";
std::string jsonExpected = "{\n"
" \"4:UINT\" : 42\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
// Signed Integer 4242, 2-octet
void TestConverter_SignedInt_2Bytes(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(7), static_cast<int16_t>(4242)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"7:INT\" : 4242\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Signed Integer -170000, 4-octet
void TestConverter_SignedInt_4Bytes(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(80), static_cast<int32_t>(-170000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"80:INT\" : -170000\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Signed Long Integer (int64_t) 40000000000, 8-octet
void TestConverter_SignedInt_8Bytes(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(202), static_cast<int64_t>(40000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"202:INT\" : \"40000000000\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Unsigned Long Integer (uint64_t) 40000000000, 8-octet
void TestConverter_UnsignedInt_8Bytes(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(222), static_cast<uint64_t>(40000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"222:UINT\" : \"40000000000\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// UTF-8 String, 1-octet length, "Hello!"
void TestConverter_UTF8String_Hello(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(0), "Hello!"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:STRING\" : \"Hello!\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Octet String, 1-octet length, octets { 00 01 02 03 04 }
void TestConverter_OctetString(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t v[] = { 0, 1, 2, 3, 4 };
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutBytes(TLV::ContextTag(1), v, sizeof(v)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:BYTES\" : \"AAECAwQ=\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Octet String, empty
void TestConverter_OctetString_Empty(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutBytes(TLV::ContextTag(1), nullptr, 0));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:BYTES\" : \"\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Null
void TestConverter_Null(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutNull(TLV::ContextTag(1)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:NULL\" : null\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Single precision floating point 0.0
void TestConverter_Float_0(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), static_cast<float>(0.0)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:FLOAT\" : 0.0\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Single precision floating point (1.0 / 3.0)
void TestConverter_Float_1third(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(100), static_cast<float>(1.0 / 3.0)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"100:FLOAT\" : 0.33333334\n"
"}\n";
std::string jsonExpected = "{\n"
" \"100:FLOAT\" : 0.3333333432674408\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
// Single precision floating point 17.9
void TestConverter_Float_17_9(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(101), static_cast<float>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"101:FLOAT\" : 17.9\n"
"}\n";
std::string jsonExpected = "{\n"
" \"101:FLOAT\" : 17.899999618530273\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
// Single precision floating point positive infinity
void TestConverter_Float_PositiveInfinity(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(101), std::numeric_limits<float>::infinity()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"101:FLOAT\" : \"Infinity\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Single precision floating point negative infinity
void TestConverter_Float_NegativeInfinity(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(101), -std::numeric_limits<float>::infinity()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"101:FLOAT\" : \"-Infinity\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Double precision floating point 0.0
void TestConverter_Double_0(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), static_cast<double>(0.0)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:DOUBLE\" : 0.0\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Double precision floating point (1.0 / 3.0)
void TestConverter_Double_1third(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(100), static_cast<double>(1.0 / 3.0)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"100:DOUBLE\" : 0.33333333333333331\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Double precision floating point 17.9
void TestConverter_Double_17_9(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(101), static_cast<double>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"101:DOUBLE\" : 17.899999999999999\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Double precision floating point positive infinity
void TestConverter_Double_PositiveInfinity(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(101), std::numeric_limits<double>::infinity()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"101:DOUBLE\" : \"Infinity\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Double precision floating point negative infinity
void TestConverter_Double_NegativeInfinity(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(101), -std::numeric_limits<double>::infinity()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"101:DOUBLE\" : \"-Infinity\"\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Empty Top-Level Structure, {}
void TestConverter_Structure_TopLevelEmpty(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{ }";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Empty Nested Structure, { {} }
void TestConverter_Structure_NestedEmpty(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:STRUCT\" : { }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Empty Array, { [] }
void TestConverter_Array_Empty(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:ARRAY-?\" : []\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
void TestConverter_Array_Empty_ImplicitProfileTag2(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite,
CHIP_NO_ERROR ==
writer.StartContainer(TLV::ProfileTag(kImplicitProfileId, 10000), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"emptyarray:10000:ARRAY-?\" : []\n"
"}\n";
std::string jsonExpected = "{\n"
" \"10000:ARRAY-?\" : []\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
void TestConverter_Array_Empty_ImplicitProfileTag4(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite,
CHIP_NO_ERROR ==
writer.StartContainer(TLV::ProfileTag((1000000 >> 16) & 0xFFFF, 0, 1000000 & 0xFFFF), TLV::kTLVType_Array,
containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1000000:ARRAY-?\" : []\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Two Signed Integers with context specific tags: {0 = 42, 1 = -17}
void TestConverter_IntsWithContextTags(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int8_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), static_cast<int8_t>(-17)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:INT\" : 42,\n"
" \"1:INT\" : -17\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Structure with Two Signed Integers with context specific tags: { {0 = 42, 1 = -17} }
void TestConverter_Struct_IntsWithContextTags(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int8_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), static_cast<int8_t>(-17)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:STRUCT\" : {\n"
" \"0:INT\" : 42,\n"
" \"1:INT\" : -17\n"
" }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Array of Signed Integers: { [0, 1, 2, 3, 4] }
void TestConverter_Array_Ints(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(0)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(1)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(2)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(3)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(4)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:ARRAY-INT\" : [\n"
" 0,\n"
" 1,\n"
" 2,\n"
" 3,\n"
" 4\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Array of Long Signed Integers: { [42, -17, -170000, 40000000000] }
void TestConverter_Array_Ints2(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(-17)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(-170000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(40000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:ARRAY-INT\" : [\n"
" 42,\n"
" -17,\n"
" -170000,\n"
" \"40000000000\"\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Array of Signed Integers with MIN/MAX values for each type int8_t/int16_t/int32_t/int64_t
void TestConverter_Array_IntsMinMax(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT8_MIN)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT8_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT16_MIN)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT16_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT32_MIN)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT32_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT64_MIN)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(INT64_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:ARRAY-INT\" : [\n"
" -128,\n"
" 127,\n"
" -32768,\n"
" 32767,\n"
" -2147483648,\n"
" 2147483647,\n"
" -9223372036854775808,\n"
" 9223372036854775807\n"
" ]\n"
"}\n";
std::string expectedString = "{\n"
" \"0:ARRAY-INT\" : [\n"
" -128,\n"
" 127,\n"
" -32768,\n"
" 32767,\n"
" -2147483648,\n"
" 2147483647,\n"
" \"-9223372036854775808\",\n"
" \"9223372036854775807\"\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, expectedString);
}
// Array of Long Unsigned Integers: { [42, 170000, 40000000000] }
void TestConverter_Array_UInts(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint64_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint64_t>(170000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint64_t>(40000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:ARRAY-UINT\" : [\n"
" 42,\n"
" 170000,\n"
" \"40000000000\"\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Array of Unsigned Integers, where each element represents MAX possible value for unsigned
// integere types uint8_t, uint16_t, uint32_t, uint64_t: [0xFF, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF_FFFFFFFF]
void TestConverter_Array_UIntsMax(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint8_t>(UINT8_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint16_t>(UINT16_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint32_t>(UINT32_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint64_t>(UINT64_MAX)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:ARRAY-UINT\" : [\n"
" 255,\n"
" 65535,\n"
" 4294967295,\n"
" 18446744073709551615\n"
" ]\n"
"}\n";
std::string expectedString = "{\n"
" \"0:ARRAY-UINT\" : [\n"
" 255,\n"
" 65535,\n"
" 4294967295,\n"
" \"18446744073709551615\"\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, expectedString);
}
// Array of Doubles: { [1.1, 134.2763, -12345.87] }
void TestConverter_Array_Doubles(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(1.1)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(134.2763)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(-12345.87)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:ARRAY-DOUBLE\" : [\n"
" 1.1,\n"
" 134.2763,\n"
" -12345.87\n"
" ]\n"
"}\n";
std::string expectedString = "{\n"
" \"0:ARRAY-DOUBLE\" : [\n"
" 1.1000000000000001,\n"
" 134.27629999999999,\n"
" -12345.870000000001\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, expectedString);
}
// Array of Floats: { [1.1, 134.2763, -12345.87] }
void TestConverter_Array_Floats(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite,
CHIP_NO_ERROR ==
writer.StartContainer(TLV::ProfileTag(kImplicitProfileId, 1000), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<float>(1.1)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<float>(134.2763)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<float>(-12345.87)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1000:ARRAY-FLOAT\" : [\n"
" 1.1,\n"
" 134.2763,\n"
" -12345.87\n"
" ]\n"
"}\n";
std::string expectedString = "{\n"
" \"1000:ARRAY-FLOAT\" : [\n"
" 1.1000000238418579,\n"
" 134.27630615234375,\n"
" -12345.8701171875\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, expectedString);
}
// Array of Strings: ["ABC", "Options", "more"]
void TestConverter_Array_Strings(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite,
CHIP_NO_ERROR ==
writer.StartContainer(TLV::ProfileTag((100000 >> 16) & 0xFFFF, 0, 100000 & 0xFFFF), TLV::kTLVType_Array,
containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "ABC"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "Options"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "more"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"100000:ARRAY-STRING\" : [\n"
" \"ABC\",\n"
" \"Options\",\n"
" \"more\"\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Array of Booleans: [true, false, false]
void TestConverter_Array_Booleans(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(255), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), false));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), false));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"255:ARRAY-BOOL\" : [\n"
" true,\n"
" false,\n"
" false\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Array of Nulls: [null, null]
void TestConverter_Array_Nulls(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutNull(TLV::AnonymousTag()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutNull(TLV::AnonymousTag()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1:ARRAY-NULL\" : [\n"
" null,\n"
" null\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Context tag 255 (max), Unsigned Integer, 1-octet value: {255 = 42U}
void TestConverter_Struct_UInt(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(255), static_cast<uint8_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"value:0:STRUCT\" : {\n"
" \"name:255:UINT\" : 42\n"
" }\n"
"}\n";
std::string jsonExpected = "{\n"
" \"0:STRUCT\" : {\n"
" \"255:UINT\" : 42\n"
" }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
// Context and Common Profile tags, Unsigned Integer structure: {255 = 42, 256 = 17000, 65535 =
// 1, 65536 = 345678, 4294967295 = 500000000000}
void TestConverter_Struct_MixedTags(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(255), static_cast<uint64_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0x0001u, 0, 0), static_cast<uint64_t>(345678)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(kImplicitProfileId, 256), static_cast<uint64_t>(17000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFFFFu, 0, 0xFFFFu), static_cast<uint64_t>(500000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(kImplicitProfileId, 65535), static_cast<uint64_t>(1)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:STRUCT\" : {\n"
" \"255:UINT\" : 42,\n"
" \"256:UINT\" : 17000,\n"
" \"65535:UINT\" : 1,\n"
" \"65536:UINT\" : 345678,\n"
" \"4294967295:UINT\" : \"500000000000\"\n"
" }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
// Structure with mixed elements
void TestConverter_Struct_MixedElements(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
char bytes[] = "Test ByteString Value";
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int64_t>(20)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<uint64_t>(0)));
NL_TEST_ASSERT(
gSuite,
CHIP_NO_ERROR ==
writer.PutBytes(TLV::ContextTag(3), reinterpret_cast<uint8_t *>(bytes), static_cast<uint32_t>(strlen(bytes))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(4), "hello"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(5), static_cast<int64_t>(-500000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(6), static_cast<double>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(7), static_cast<float>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"c:0:STRUCT\" : {\n"
" \"z:0:INT\" : 20,\n"
" \"b:1:BOOL\" : true,\n"
" \"2:UINT\" : 0,\n"
" \"abc:3:BYTES\" : \"VGVzdCBCeXRlU3RyaW5nIFZhbHVl\",\n"
" \"cc:4:STRING\" : \"hello\",\n"
" \"tt:5:INT\" : -500000,\n"
" \"AA:6:DOUBLE\" : 17.9,\n"
" \"B:7:FLOAT\" : 17.9\n"
" }\n"
"}\n";
std::string expectedString = "{\n"
" \"0:STRUCT\" : {\n"
" \"0:INT\" : 20,\n"
" \"1:BOOL\" : true,\n"
" \"2:UINT\" : 0,\n"
" \"3:BYTES\" : \"VGVzdCBCeXRlU3RyaW5nIFZhbHVl\",\n"
" \"4:STRING\" : \"hello\",\n"
" \"5:INT\" : -500000,\n"
" \"6:DOUBLE\" : 17.899999999999999,\n"
" \"7:FLOAT\" : 17.899999618530273\n"
" }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, expectedString);
}
// Array of structures with mixed elements
void TestConverter_Array_Structures(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
TLV::TLVType containerType3;
char bytes1[] = "Test ByteString Value 1";
char bytes2[] = "Test ByteString Value 2";
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite,
CHIP_NO_ERROR ==
writer.StartContainer(TLV::ProfileTag(kImplicitProfileId, 1000), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int64_t>(20)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<uint64_t>(0)));
NL_TEST_ASSERT(
gSuite,
CHIP_NO_ERROR ==
writer.PutBytes(TLV::ContextTag(3), reinterpret_cast<uint8_t *>(bytes1), static_cast<uint32_t>(strlen(bytes1))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(4), "hello1"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(5), static_cast<int64_t>(-500000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(6), static_cast<double>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(7), static_cast<float>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int64_t>(-10)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), false));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<uint64_t>(128)));
NL_TEST_ASSERT(
gSuite,
CHIP_NO_ERROR ==
writer.PutBytes(TLV::ContextTag(3), reinterpret_cast<uint8_t *>(bytes2), static_cast<uint32_t>(strlen(bytes2))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(4), "hello2"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(5), static_cast<int64_t>(40000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(6), static_cast<double>(-1754.923)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(7), static_cast<float>(97.945)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"1000:ARRAY-STRUCT\": [\n"
" {\n"
" \"0:INT\" : 20,\n"
" \"1:BOOL\" : true,\n"
" \"2:UINT\" : 0,\n"
" \"3:BYTES\" : \"VGVzdCBCeXRlU3RyaW5nIFZhbHVlIDE=\",\n"
" \"4:STRING\" : \"hello1\",\n"
" \"5:INT\" : -500000,\n"
" \"6:DOUBLE\" : 17.9,\n"
" \"7:FLOAT\" : 17.9\n"
" },\n"
" {\n"
" \"0:INT\" : -10,\n"
" \"1:BOOL\" : false,\n"
" \"2:UINT\" : 128,\n"
" \"3:BYTES\" : \"VGVzdCBCeXRlU3RyaW5nIFZhbHVlIDI=\",\n"
" \"4:STRING\" : \"hello2\",\n"
" \"5:INT\" : \"40000000000\",\n"
" \"6:DOUBLE\" : -1754.923,\n"
" \"7:FLOAT\" : 97.945\n"
" }\n"
" ]\n"
"}\n";
std::string expectedString = "{\n"
" \"1000:ARRAY-STRUCT\": [\n"
" {\n"
" \"0:INT\" : 20,\n"
" \"1:BOOL\" : true,\n"
" \"2:UINT\" : 0,\n"
" \"3:BYTES\" : \"VGVzdCBCeXRlU3RyaW5nIFZhbHVlIDE=\",\n"
" \"4:STRING\" : \"hello1\",\n"
" \"5:INT\" : -500000,\n"
" \"6:DOUBLE\" : 17.899999999999999,\n"
" \"7:FLOAT\" : 17.899999618530273\n"
" },\n"
" {\n"
" \"0:INT\" : -10,\n"
" \"1:BOOL\" : false,\n"
" \"2:UINT\" : 128,\n"
" \"3:BYTES\" : \"VGVzdCBCeXRlU3RyaW5nIFZhbHVlIDI=\",\n"
" \"4:STRING\" : \"hello2\",\n"
" \"5:INT\" : \"40000000000\",\n"
" \"6:DOUBLE\" : -1754.923,\n"
" \"7:FLOAT\" : 97.944999694824219\n"
" }\n"
" ]\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, expectedString);
}
// Top level with mixed elements
void TestConverter_TopLevel_MixedElements(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
TLV::TLVType containerType3;
char bytes[] = "Test array member 0";
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int64_t>(42)));
NL_TEST_ASSERT(
gSuite,
CHIP_NO_ERROR ==
writer.PutBytes(TLV::ContextTag(1), reinterpret_cast<uint8_t *>(bytes), static_cast<uint32_t>(strlen(bytes))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<double>(156.398)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(3), static_cast<uint64_t>(73709551615)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(4), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutNull(TLV::ContextTag(5)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(6), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(1), "John"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<uint64_t>(34)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(3), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(4), TLV::kTLVType_Array, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(5)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(10)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(5), TLV::kTLVType_Array, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "Ammy"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "David"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "Larry"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(6), TLV::kTLVType_Array, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), false));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(7), static_cast<float>(0.0)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"value:0:INT\": 42,\n"
" \"value:1:BYTES\": \"VGVzdCBhcnJheSBtZW1iZXIgMA==\",\n"
" \"value:2:DOUBLE\": 156.398,\n"
" \"value:3:UINT\": \"73709551615\",\n"
" \"value:4:BOOL\": true,\n"
" \"value:5:NULL\": null,\n"
" \"value:6:STRUCT\": {\n"
" \"name:1:STRING\": \"John\",\n"
" \"age:2:UINT\": 34,\n"
" \"approved:3:BOOL\": true,\n"
" \"kids:4:ARRAY-INT\": [\n"
" 5,\n"
" 9,\n"
" 10\n"
" ],\n"
" \"names:5:ARRAY-STRING\": [\n"
" \"Ammy\",\n"
" \"David\",\n"
" \"Larry\"\n"
" ],\n"
" \"6:ARRAY-BOOL\": [\n"
" true,\n"
" false,\n"
" true\n"
" ]\n"
" },\n"
" \"value:7:FLOAT\": 0.0\n"
"}\n";
std::string jsonExpected = "{\n"
" \"0:INT\": 42,\n"
" \"1:BYTES\": \"VGVzdCBhcnJheSBtZW1iZXIgMA==\",\n"
" \"2:DOUBLE\": 156.398,\n"
" \"3:UINT\": \"73709551615\",\n"
" \"4:BOOL\": true,\n"
" \"5:NULL\": null,\n"
" \"6:STRUCT\": {\n"
" \"1:STRING\": \"John\",\n"
" \"2:UINT\": 34,\n"
" \"3:BOOL\": true,\n"
" \"4:ARRAY-INT\": [\n"
" 5,\n"
" 9,\n"
" 10\n"
" ],\n"
" \"5:ARRAY-STRING\": [\n"
" \"Ammy\",\n"
" \"David\",\n"
" \"Larry\"\n"
" ],\n"
" \"6:ARRAY-BOOL\": [\n"
" true,\n"
" false,\n"
" true\n"
" ]\n"
" },\n"
" \"7:FLOAT\": 0.0\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
// Complex Structure from README
void TestConverter_Structure_FromReadme(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
TLV::TLVType containerType3;
uint8_t bytes1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };
uint8_t bytes2[] = { 0xFF };
uint8_t bytes3[] = { 0x4A, 0xEF, 0x88 };
char bytes4[] = "Test Bytes";
writer.Init(buf);
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int8_t>(8)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(0), static_cast<int8_t>(12)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), false));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(2), "example"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<int64_t>(40000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(3), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(4), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(5), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(1.1)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(134.2763)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(-12345.87)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), std::numeric_limits<double>::infinity()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(62534)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<double>(-62534)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(6), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutBytes(TLV::AnonymousTag(), bytes1, static_cast<uint32_t>(sizeof(bytes1))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutBytes(TLV::AnonymousTag(), bytes2, static_cast<uint32_t>(sizeof(bytes2))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutBytes(TLV::AnonymousTag(), bytes3, static_cast<uint32_t>(sizeof(bytes3))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(
gSuite,
CHIP_NO_ERROR ==
writer.PutBytes(TLV::ContextTag(7), reinterpret_cast<uint8_t *>(bytes4), static_cast<uint32_t>(strlen(bytes4))));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(8), static_cast<double>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(9), static_cast<float>(17.9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(10), -std::numeric_limits<float>::infinity()));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(11), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::ContextTag(1), "John"));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(2), static_cast<uint32_t>(34)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(3), true));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(4), TLV::kTLVType_Array, containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(5)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(9)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int8_t>(10)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType3));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
std::string jsonString = "{\n"
" \"0:ARRAY-STRUCT\" : [\n"
" {\n"
" \"0:INT\" : 8,\n"
" \"1:BOOL\" : true\n"
" }\n"
" ],\n"
" \"1:STRUCT\" : {\n"
" \"0:INT\" : 12,\n"
" \"1:BOOL\" : false,\n"
" \"2:STRING\" : \"example\"\n"
" },\n"
" \"2:INT\" : \"40000000000\",\n"
" \"isQualified:3:BOOL\" : true,\n"
" \"4:ARRAY-?\" : [],\n"
" \"5:ARRAY-DOUBLE\" : [\n"
" 1.1000000000000001,\n"
" 134.27629999999999,\n"
" -12345.870000000001,\n"
" \"Infinity\",\n"
" 62534.0,\n"
" -62534.0\n"
" ],\n"
" \"6:ARRAY-BYTES\" : [\n"
" \"AAECAwQ=\",\n"
" \"/w==\",\n"
" \"Su+I\"\n"
" ],\n"
" \"7:BYTES\" : \"VGVzdCBCeXRlcw==\",\n"
" \"8:DOUBLE\" : 17.899999999999999,\n"
" \"9:FLOAT\" : 17.899999618530273,\n"
" \"10:FLOAT\" : \"-Infinity\",\n"
" \"contact:11:STRUCT\" : {\n"
" \"name:1:STRING\" : \"John\",\n"
" \"age:2:UINT\" : 34,\n"
" \"approved:3:BOOL\" : true,\n"
" \"kids:4:ARRAY-INT\" : [\n"
" 5,\n"
" 9,\n"
" 10\n"
" ]\n"
" }\n"
"}\n";
std::string jsonExpected = "{\n"
" \"0:ARRAY-STRUCT\" : [\n"
" {\n"
" \"0:INT\" : 8,\n"
" \"1:BOOL\" : true\n"
" }\n"
" ],\n"
" \"1:STRUCT\" : {\n"
" \"0:INT\" : 12,\n"
" \"1:BOOL\" : false,\n"
" \"2:STRING\" : \"example\"\n"
" },\n"
" \"2:INT\" : \"40000000000\",\n"
" \"3:BOOL\" : true,\n"
" \"4:ARRAY-?\" : [],\n"
" \"5:ARRAY-DOUBLE\" : [\n"
" 1.1000000000000001,\n"
" 134.27629999999999,\n"
" -12345.870000000001,\n"
" \"Infinity\",\n"
" 62534.0,\n"
" -62534.0\n"
" ],\n"
" \"6:ARRAY-BYTES\" : [\n"
" \"AAECAwQ=\",\n"
" \"/w==\",\n"
" \"Su+I\"\n"
" ],\n"
" \"7:BYTES\" : \"VGVzdCBCeXRlcw==\",\n"
" \"8:DOUBLE\" : 17.899999999999999,\n"
" \"9:FLOAT\" : 17.899999618530273,\n"
" \"10:FLOAT\" : \"-Infinity\",\n"
" \"11:STRUCT\" : {\n"
" \"1:STRING\" : \"John\",\n"
" \"2:UINT\" : 34,\n"
" \"3:BOOL\" : true,\n"
" \"4:ARRAY-INT\" : [\n"
" 5,\n"
" 9,\n"
" 10\n"
" ]\n"
" }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonExpected);
}
void TestConverter_TlvToJson_ErrorCases(nlTestSuite * inSuite, void * inContext)
{
CHIP_ERROR err;
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
struct TestCase
{
const ByteSpan nEncodedTlv;
CHIP_ERROR mExpectedResult;
const char * mNameString;
};
uint8_t buf1[32];
writer.Init(buf1);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::CommonTag(1), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), true));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Finalize());
ByteSpan topLevelStructWithTag(buf1, writer.GetLengthWritten());
uint8_t buf2[32];
writer.Init(buf2);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), true));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Finalize());
ByteSpan topLevelIsArray(buf2, writer.GetLengthWritten());
uint8_t buf3[32];
writer.Init(buf3);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_List, containerType2));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(1), true));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Finalize());
ByteSpan usingList(buf3, writer.GetLengthWritten());
uint8_t buf8[32];
writer.Init(buf8);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Array, containerType2));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint64_t>(42)));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<int64_t>(-170000)));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::AnonymousTag(), static_cast<uint64_t>(42456)));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Finalize());
ByteSpan arrayWithMixedElements(buf8, writer.GetLengthWritten());
uint8_t buf9[32];
writer.Init(buf9);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFEED, 234), static_cast<uint64_t>(42)));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Finalize());
ByteSpan useFullyQualifiedTag(buf9, writer.GetLengthWritten());
// clang-format off
static const TestCase sTestCases[] = {
// TLV Encoded Input Expected Error Test Case String
// ==================================================================================================
{ topLevelStructWithTag, CHIP_ERROR_INVALID_TLV_TAG, "Top-Level Struct is Not Anonymous" },
{ topLevelIsArray, CHIP_ERROR_WRONG_TLV_TYPE, "Top-Level is an Array" },
{ usingList, CHIP_ERROR_INVALID_TLV_ELEMENT, "Using Unsupported List Type" },
{ arrayWithMixedElements, CHIP_ERROR_INVALID_TLV_ELEMENT, "Array with Mixed Elements" },
{ useFullyQualifiedTag, CHIP_ERROR_INVALID_TLV_TAG, "Using Unsupported Fully Qualified Tag" },
};
// clang-format on
for (const auto & testCase : sTestCases)
{
std::string jsonString;
err = TlvToJson(testCase.nEncodedTlv, jsonString);
NL_TEST_ASSERT(inSuite, err == testCase.mExpectedResult);
}
}
void TestConverter_JsonToTlv_ErrorCases(nlTestSuite * inSuite, void * inContext)
{
CHIP_ERROR err;
struct TestCase
{
const std::string mJsonString;
CHIP_ERROR mExpectedResult;
const char * mNameString;
};
std::string arrayTypeStringExpectedBool = "{\n"
" \"value:1:ARRAY-BOOL\" : [\n"
" \"yes\",\n"
" \"no\"\n"
" ]\n"
"}\n";
std::string arrayTypeIntExpectedUInt = "{\n"
" \"value:1:ARRAY-UINT\" : [\n"
" 45,\n"
" -367\n"
" ]\n"
"}\n";
std::string arrayElementsWithName = "{\n"
" \"value:1:ARRAY-INT\" : [\n"
" \"1:INT\" : 45,\n"
" \"2:INT\" : -367\n"
" ]\n"
"}\n";
std::string invalidNameWithoutTagField = "{\n"
" \"value:ARRAY-BYTES\" : [\n"
" \"AAECAwQ=\"\n"
" ]\n"
"}\n";
std::string invalidNameWithoutTagField2 = "{\n"
" \"UINT\" : 42\n"
"}\n";
std::string invalidNameWithNegativeTag = "{\n"
" \"-1:UINT\" : 42\n"
"}\n";
std::string invalidNameWithInvalidTypeField = "{\n"
" \"1:INTEGER\" : 42\n"
"}\n";
std::string invalidBytesBase64Value1 = "{\n"
" \"1:BYTES\" : \"SGVsbG8!\"\n"
"}\n";
std::string invalidBytesBase64Value2 = "{\n"
" \"1:BYTES\" : \"AAECw=Q\"\n"
"}\n";
std::string invalidBytesBase64Value3 = "{\n"
" \"1:BYTES\" : \"AAECwQ=\"\n"
"}\n";
std::string invalidBytesBase64Value4 = "{\n"
" \"1:BYTES\" : \"AAECwQ\"\n"
"}\n";
std::string invalidBytesBase64Padding1 = "{\n"
" \"1:BYTES\" : \"=\"\n"
"}\n";
std::string invalidBytesBase64Padding2 = "{\n"
" \"1:BYTES\" : \"==\"\n"
"}\n";
std::string invalidBytesBase64Padding3 = "{\n"
" \"1:BYTES\" : \"===\"\n"
"}\n";
std::string invalidPositiveInfinityValue = "{\n"
" \"1:DOUBLE\" : \"+Infinity\"\n"
"}\n";
std::string invalidFloatValueAsString = "{\n"
" \"1:FLOAT\" : \"1.1\"\n"
"}\n";
// clang-format off
static const TestCase sTestCases[] = {
// Json String Expected Error Test Case String
// ==========================================================================================================================
{ arrayTypeStringExpectedBool, CHIP_ERROR_INVALID_ARGUMENT, "Array Type Is String While Bool Is Expected" },
{ arrayTypeIntExpectedUInt, CHIP_ERROR_INVALID_ARGUMENT, "Array Type Is Signed Integer While Unsigned Is Expected" },
{ arrayElementsWithName, CHIP_ERROR_INTERNAL, "Array Elements With Json Name" },
{ invalidNameWithoutTagField, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name String Without Tag Field" },
{ invalidNameWithoutTagField2, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name String Without Tag Field 2" },
{ invalidNameWithNegativeTag, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name With Negative Tag Value" },
{ invalidNameWithInvalidTypeField, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name With Invalid Type Field" },
{ invalidBytesBase64Value1, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid Character" },
{ invalidBytesBase64Value2, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid Character" },
{ invalidBytesBase64Value3, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid padding (missing 1)" },
{ invalidBytesBase64Value4, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid padding (missing 2)" },
{ invalidBytesBase64Padding1, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid padding (start 1)" },
{ invalidBytesBase64Padding2, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid padding (start 2)" },
{ invalidBytesBase64Padding3, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid padding (start 3)" },
{ invalidPositiveInfinityValue, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Double Positive Infinity Encoding" },
{ invalidFloatValueAsString, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Float Value Encoding as a String" },
};
// clang-format on
for (const auto & testCase : sTestCases)
{
uint8_t buf[256];
MutableByteSpan tlvSpan(buf);
err = JsonToTlv(testCase.mJsonString, tlvSpan);
NL_TEST_ASSERT(inSuite, err == testCase.mExpectedResult);
#if CHIP_CONFIG_ERROR_FORMAT_AS_STRING
if (err != testCase.mExpectedResult)
{
std::string errStr{ err.Format() };
std::string expectedErrStr{ testCase.mExpectedResult.Format() };
printf("Case: %s, Error: %" CHIP_ERROR_FORMAT ", Expected: %" CHIP_ERROR_FORMAT ", Data: %s\n", testCase.mNameString,
errStr.c_str(), expectedErrStr.c_str(), testCase.mJsonString.c_str());
}
#endif // CHIP_CONFIG_ERROR_FORMAT_AS_STRING
}
}
// Full Qualified Profile tags, Unsigned Integer structure: {65536 = 42, 4294901760 = 17000, 4294967295 = 500000000000}
void TestConverter_Struct_MEITags(nlTestSuite * inSuite, void * inContext)
{
gSuite = inSuite;
uint8_t buf[256];
TLV::TLVWriter writer;
TLV::TLVType containerType;
TLV::TLVType containerType2;
writer.Init(buf);
writer.ImplicitProfileId = kImplicitProfileId;
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFFFFu, 0, 0), static_cast<uint64_t>(17000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0x0001u, 0, 0), static_cast<uint64_t>(42)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFFFFu, 0, 0xFFFFu), static_cast<uint64_t>(500000000000)));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType));
NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize());
std::string jsonString = "{\n"
" \"0:STRUCT\" : {\n"
" \"65536:UINT\" : 42,\n"
" \"4294901760:UINT\" : 17000,\n"
" \"4294967295:UINT\" : \"500000000000\"\n"
" }\n"
"}\n";
ByteSpan tlvSpan(buf, writer.GetLengthWritten());
CheckValidConversion(jsonString, tlvSpan, jsonString);
}
int Initialize(void * apSuite)
{
VerifyOrReturnError(chip::Platform::MemoryInit() == CHIP_NO_ERROR, FAILURE);
return SUCCESS;
}
int Finalize(void * aContext)
{
chip::Platform::MemoryShutdown();
return SUCCESS;
}
const nlTest sTests[] = {
NL_TEST_DEF("Test Json Tlv Converter - Boolean True", TestConverter_Boolean_True),
NL_TEST_DEF("Test Json Tlv Converter - Signed Integer 1-Byte Positive", TestConverter_SignedInt_1BytePositive),
NL_TEST_DEF("Test Json Tlv Converter - Signed Integer 1-Byte Negative", TestConverter_SignedInt_1ByteNegative),
NL_TEST_DEF("Test Json Tlv Converter - Unsigned Integer 1-Byte", TestConverter_UnsignedInt_1Byte),
NL_TEST_DEF("Test Json Tlv Converter - Signed Integer 2-Bytes", TestConverter_SignedInt_2Bytes),
NL_TEST_DEF("Test Json Tlv Converter - Signed Integer 4-Bytes", TestConverter_SignedInt_4Bytes),
NL_TEST_DEF("Test Json Tlv Converter - Signed Integer 8-Bytes", TestConverter_SignedInt_8Bytes),
NL_TEST_DEF("Test Json Tlv Converter - Unsigned Integer 8-Bytes", TestConverter_UnsignedInt_8Bytes),
NL_TEST_DEF("Test Json Tlv Converter - UTF-8 String Hello!", TestConverter_UTF8String_Hello),
NL_TEST_DEF("Test Json Tlv Converter - Octet String", TestConverter_OctetString),
NL_TEST_DEF("Test Json Tlv Converter - Empty Octet String", TestConverter_OctetString_Empty),
NL_TEST_DEF("Test Json Tlv Converter - Null", TestConverter_Null),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Single Precision 0.0", TestConverter_Float_0),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Single Precision 1/3", TestConverter_Float_1third),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Single Precision 17.9", TestConverter_Float_17_9),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Single Precision Positive Infinity",
TestConverter_Float_PositiveInfinity),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Single Precision Negative Infinity",
TestConverter_Float_NegativeInfinity),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Double Precision 0.0", TestConverter_Double_0),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Double Precision 1/3", TestConverter_Double_1third),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Double Precision 17.9", TestConverter_Double_17_9),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Double Precision Positive Infinity",
TestConverter_Double_PositiveInfinity),
NL_TEST_DEF("Test Json Tlv Converter - Floating Point Double Precision Negative Infinity",
TestConverter_Double_NegativeInfinity),
NL_TEST_DEF("Test Json Tlv Converter - Structure Top-Level Empty", TestConverter_Structure_TopLevelEmpty),
NL_TEST_DEF("Test Json Tlv Converter - Structure Nested Empty", TestConverter_Structure_NestedEmpty),
NL_TEST_DEF("Test Json Tlv Converter - Array Empty", TestConverter_Array_Empty),
NL_TEST_DEF("Test Json Tlv Converter - Array Empty with Implicit Profile Tag (length 2)",
TestConverter_Array_Empty_ImplicitProfileTag2),
NL_TEST_DEF("Test Json Tlv Converter - Array Empty with Implicit Profile Tag (length 4)",
TestConverter_Array_Empty_ImplicitProfileTag4),
NL_TEST_DEF("Test Json Tlv Converter - Two Signed Integers", TestConverter_IntsWithContextTags),
NL_TEST_DEF("Test Json Tlv Converter - Structure With Two Signed Integers", TestConverter_Struct_IntsWithContextTags),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Signed Integers", TestConverter_Array_Ints),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Long Signed Integers", TestConverter_Array_Ints2),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Min/Max Signed Integers", TestConverter_Array_IntsMinMax),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Long Unsigned Integers", TestConverter_Array_UInts),
NL_TEST_DEF("Test Json Tlv Converter - Array of Unsigned Integers with Max values", TestConverter_Array_UIntsMax),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Doubles", TestConverter_Array_Doubles),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Floats", TestConverter_Array_Floats),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Strings", TestConverter_Array_Strings),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Booleans", TestConverter_Array_Booleans),
NL_TEST_DEF("Test Json Tlv Converter - Array Of Nulls", TestConverter_Array_Nulls),
NL_TEST_DEF("Test Json Tlv Converter - Structure with Unsigned Integer", TestConverter_Struct_UInt),
NL_TEST_DEF("Test Json Tlv Converter - Structure Elements with Mixed Tags", TestConverter_Struct_MixedTags),
NL_TEST_DEF("Test Json Tlv Converter - Structure with Mixed Elements", TestConverter_Struct_MixedElements),
NL_TEST_DEF("Test Json Tlv Converter - Array of Structures with Mixed Elements", TestConverter_Array_Structures),
NL_TEST_DEF("Test Json Tlv Converter - Top-Level Structure with Mixed Elements", TestConverter_TopLevel_MixedElements),
NL_TEST_DEF("Test Json Tlv Converter - Complex Structure from the README File", TestConverter_Structure_FromReadme),
NL_TEST_DEF("Test Json Tlv Converter - Tlv to Json Error Cases", TestConverter_TlvToJson_ErrorCases),
NL_TEST_DEF("Test Json Tlv Converter - Json To Tlv Error Cases", TestConverter_JsonToTlv_ErrorCases),
NL_TEST_DEF("Test Json Tlv Converter - Structure with MEI Elements", TestConverter_Struct_MEITags),
NL_TEST_SENTINEL()
};
} // namespace
int TestJsonToTlvToJson()
{
nlTestSuite theSuite = { "JsonToTlvToJson", sTests, Initialize, Finalize };
nlTestRunner(&theSuite, nullptr);
return nlTestRunnerStats(&theSuite);
}
CHIP_REGISTER_TEST_SUITE(TestJsonToTlvToJson)